本章将讲解一些管对对象和基础编程的知识。如:类,接口,抽象类,数据类,扩展方法等
其实这部分的设计思路和Java基本一致。这里主要说下Kotlin特有的属性
abstract class Manager : Driver, Writer {
override fun driver() {
}
override fun writer() {
}
}
interface Driver {
fun driver(){
println("driver")
}
}
class CarDriver : Driver {
override fun driver() {
println("开车")//接口的默认实现
}
}
interface Writer {
fun writer()
}
class PPTWriter : Writer {
override fun writer() {
println("写PPT")
}
}
class SeniorManager(val driver: Driver, val writer: Writer) : Driver by driver, Writer by writer {//实现忌口但是通过by关键字可以不用去实现里面的接口方法
}
/**
* 不加by关键字那么就要实现接口的方法
*/
class SeniorManager1(val driver: Driver, val writer: Writer) : Driver, Writer {
override fun driver() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun writer() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
fun main(args: Array) {
val driver = CarDriver()
val writer = PPTWriter()
val seniorManager = SeniorManager(driver, writer)
seniorManager.driver()
seniorManager.writer()
}
接口是约定,抽象类本是是类的一种:
abstract class Person(val age: Int) {
open fun work() {
}
}
abstract class Person1(open val age: Int = 3) {
abstract fun work()
}
class MaNong(age: Int) : Person(age) {
override fun work() {
super.work()
println("我是码农,我在写代码")
}
}
class Doctor(age: Int) : Person1(age) {
override val age: Int
get() = 6//5.传入后又重写
override fun work() {
println("我是医生,我给人看病")
}
}
Kotlin | Java |
---|---|
private | private |
protected↑ | protected |
- | default (包内可见) |
internal (模块Module内可见) | - |
public | public |
例子:
interface Listener {
fun start()
fun stop()
}
abstract class Player
object MusicPlayer : Player(), Listener {//可以实现接口,继承父类
override fun start() {
}
override fun stop() {
}
val state = 0//可以有成员属性
fun continuePlay() {//可以有方法
}
}
fun main(args: Array) {
val music: MusicPlayer = MusicPlayer//后面没有括号,也就是说明不是调用构造方法创建的对象
}
kotlin 中时没有static 这种方法修饰的静态方法 所以要实现 类似于java中的静态属性就要用到伴生对象
例子:
fun main(args: Array) {
/**
* 这时候调用伴生对象就相当于调用java静态方法 格式相同
*/
val value = Latitude.ofDouble(3.0)
println(Latitude.TAG)
}
/**
* 私有的构造方法 companion伴生对象关键字
*/
class Latitude private constructor(val latitude: Double) {
companion object {
fun ofDouble(double: Double): Latitude {
return Latitude(double)
}
@JvmStatic//加上这个注解可以在Java中如static一样调用
fun ofLatitude(latitude: Latitude): Latitude {
return Latitude(latitude.latitude)
}
@JvmField//加上这个注解可以在Java中如static一样调用
val TAG = "Latitude"
}
}
与Java相同,,需要注意一下几点
为现有类添加方法、属性:
例子:
//自己定义一个扩展方法 方法的名字是 类型.方法名
fun String.copy(int: Int): String {
val buildStr = StringBuilder()
for (i in 0 until int) {
buildStr.append("abc")
}
return buildStr.toString()
}
//也可以用操作符
operator fun String.times(int: Int): String {
val buildStr = StringBuilder()
for (i in 0 until int) {
buildStr.append("abc")
}
return buildStr.toString()
}
输出:
fun main(args: Array) {
println("abc".copy(5))
println("abc" * 5)//操作符 times对应* 具体参照文档 https://kotlinlang.org/docs/reference/operator-overloading.html
}
代理的场景 比如定义一个属性外界去访问,可以在getValue去读取一个文件setValue去写入一个文件那么就相当于与读取一个就可以文件,调用处代码变得非常简洁
class Delegates4_9 {
val hello by lazy {
//懒加载 只有第一次使用的时候才回去初始化
"helloWorld"
}
val hello2 by LazyX()//代理 //不可变代理 使用2处代码
var hello3 by LazyX()//代理
}
class LazyX {
var value: String? = null
//仿写Lazy 2
// operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
// return "Hello Lazy"
// }
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("getValue: $thisRef ->${property.name}")
return "Hello Lazy"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("setValue: $thisRef ->${property.name} = $value")
this.value = value
}
}
fun main(args: Array) {
val delegates = Delegates4_9()
println(delegates.hello)
println(delegates.hello2)
println(delegates.hello3)
delegates.hello3 = "value of hello3"
println(delegates.hello3)
}
主要是讲解data关键字,data主要是帮助生成copy,toString,componentN(对应返回定义的参数) hasCode,equals等方法,默认是没有无参数的构造方法并且生成的类是final的,需要用allOpen去掉final,noArg创建无参数构造函数
allOpen/noArg:
appModule下build.gradle
apply plugin: 'kotlin-noarg'
apply plugin: 'kotlin-allopen'
noArg {
annotation("packageName.Poko")
}
allOpen {
annotation("packageName.Poko")
}
项目下的build.gradle:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:1.3.21"
classpath "org.jetbrains.kotlin:kotlin-allopen:1.3.21"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
使用:
@Poko
data class Country4_10(val id: Int, val name: String)
Kotlin的内部类与Java内部类概念相同。存在以下几种不同点:
例子:
class Outter {
val a = 0
class Inner {
fun main(args: Array) {
// println(a)//访问不到 说明kotlin中默认是使用静态static内部类的
println(Outter().a)
}
}
inner class Inner1 {
//inner关键字 变成非静态 这样就可以访问到外部类的属性的
val a = 6
fun main(args: Array) {
// println(a)//访问不到 说明kotlin中默认是使用静态static内部类的
println([email protected])//当内外部类重载相同的属性或方法时 通过this@Outter访问
println([email protected])
println(a)
}
}
}
interface OnClickListener {
fun click()
}
class View {
var onClickListener: OnClickListener? = null
}
open class Text
fun main(args: Array) {
val view = View()
view.onClickListener = object : Text(), OnClickListener {
//java 匿名内部类是不能继承的 kotlin可以
//用object关键字来实例化内部类
override fun click() {
}
}
}
基本与Java一致。例子:
enum class LogcatLevel(val id: Int) {
VERBOSE(5), DEBUG(6), INFO(7), WARN(8), ERROR(9), ASSERT(10);//枚举类可以定义方法
fun getTag(): String {
return "$name , $id"
}
override fun toString(): String {
return "$name , $ordinal"
}
}
Kotlin枚举类中定义方法,那么要在枚举对象最后加上; 这基本是Kotlin中唯一一个需要强制写;的地方
记过这4篇文章的学习,基本已经掌握Kotlin的基本语法和对Java的对比,也顺带复习了一下Java的知识,下一篇我们来学习一些关于Kotlin的高阶函数
Github源码直接运行,包含全部详细笔记