• Kotlin学习之面向对象


    定义普通类

    fun main(args: Array<String>) {
        val person = Person("lisi")  //不需要使用new关键字
        println(person) //useranme:lisi,age:20
        val person2 = Person("lisi", 23)
        println(person2) //useranme:lisi,age:23
    }
    
    class Person constructor(username: String) {
        private var username: String
        private var age: Int
    
        init {
            // 通过主构造器为属性赋值
            this.username = username
            this.age = 20
        }
        // 次构造器
        constructor(username: String, age: Int) : this(username) {
            this.age = age
        }
        // 重写toString()方法
        override fun toString(): String {
            return "useranme:$username,age:$age"
        }
    }
    

    每个类都有一个主构造器和多个次构造器(可以没有),
    主构造器是类头部的一部分,位于类名称之后,init初始化块为属性赋值,
    次构造器使用constructor前缀,每个次构造器要直接或间接的调用主构造器。

    class Person constructor(private val username: String) {
        override fun toString(): String {
            return "username:$username"
        }
    }
    

    这是一种简化的写法,通过主构造器定义属性并初始化。

    getter和setter

    fun main(args: Array<String>) {
        val person = Person("lisi")
        println(person.username)
        person.username = "lisi2"
        println(person.username)
    }
    
    class Person constructor(username: String) {
        var username: String = username
            get() {
                println("get invoked")
                return field
            }
            set(value) {
                println("set invoked")
                field = value
            }
    }
    

    访问属性默认调用属性的get()方法,修改属性默认调用属性的set()方法,如果我们没有定义,kotlin会自动生成getter和setter。

    嵌套类和内部类

    fun main(args: Array<String>) {
        println(Person.NestedClass())
        println(Person().InnerClass())
    }
    
    class Person {
        //嵌套类
        class NestedClass
        //内部类
        inner class InnerClass
    }
    

    嵌套类类似java的静态内部类,内部类类似java的非静态内部类。

    继承

    fun main(args: Array<String>) {
        val person = Child("lisi")
        person.printUsername()
    }
    // 父类
    open class Parent constructor(private val username: String) {
        open fun printUsername() {
            println(this.username)
        }
    }
    // 子类
    class Child(private val username: String) : Parent(username) {
        //方法重写,且不能被再次重写
        final override fun printUsername() {
            println(this.username)
        }
    }
    

    kotlin中所有类默认继承于Any,且默认不可被继承,open标识符表示类可以被继承或方法可以被重写。
    通过override标识符重写父类的方法,final表示不允许被子类再次重写。

    定义接口

    fun main(args: Array<String>) {
        val person = UserService()
        person.saveUser("张三")
    }
    // 定义接口
    interface IUserService {
        fun getUser(): String
        fun saveUser(user: String) {
            println(this.getUser())
        }
    }
    // 定义实现类
    class UserService : IUserService {
        override fun getUser(): String {
            return "lisi"
        }
    }
    

    kotlin中接口的方法也可以有默认实现,类似java中接口的默认方法。

    扩展函数和属性

    fun main(args: Array<String>) {
        val person = Person("lisi")
        person.printUsername()
        println(person.age)
    }
    class Person(private val username: String) {
        fun getUsername(): String {
            return username;
        }
    }
    // 为Person类扩展一个方法
    fun Person.printUsername() {
        println(this.getUsername())
    }
    // 为Person类扩展一个属性
    val Person.age: Int
        get() = 20
    

    扩展函数不会对目标类做修改,静态解析,不支持多态。

    fun main(args: Array<String>) {
        printName(Child()) //Parent
    }
    
    open class Parent {
    }
    class Child : Parent() {
    }
    fun Parent.name() = "Parent"
    fun Child.name() = "Child"
    
    fun printName(p: Parent) {
        println(p.name())
    }
    

    我们对父类和子类都扩展了name()方法,printName()方法的参数声明为Parent,所以调用的扩展方法为Parent的name()方法,和参数的实际类型无关。反编译结果为

    点击查看代码
    public final class FirstDemoKt {
       public static final void main(@NotNull String[] args) {
          Intrinsics.checkParameterIsNotNull(args, "args");
          printName((Parent)(new Child()));
       }
    
       @NotNull
       public static final String name(@NotNull Parent $receiver) {
          Intrinsics.checkParameterIsNotNull($receiver, "receiver$0");
          return "Parent";
       }
    
       @NotNull
       public static final String name(@NotNull Child $receiver) {
          Intrinsics.checkParameterIsNotNull($receiver, "receiver$0");
          return "Child";
       }
    
       public static final void printName(@NotNull Parent p) {
          Intrinsics.checkParameterIsNotNull(p, "p");
          String var1 = name(p);
          System.out.println(var1);
       }
    }
    

    对象表达式

    fun main(args: Array<String>) {
        val obj = object {
            fun method() = "hello"
        }
        println(obj.method())
    }
    

    类似java的匿名内部类,但功能更加强大。

    对象声明

    fun main(args: Array<String>) {
        Person.test("lisi")
    }
    // 对象声明
    object Person {
        fun test(p: String) {
            println(p)
        }
    }
    

    可以看做声明了一个单例对象,反编译结果为

    点击查看代码
    public final class FirstDemoKt {
       public static final void main(@NotNull String[] args) {
          Intrinsics.checkParameterIsNotNull(args, "args");
          Person.INSTANCE.test("lisi");
       }
    }
    
    public final class Person {
       public static final Person INSTANCE;
    
       public final void test(@NotNull String p) {
          Intrinsics.checkParameterIsNotNull(p, "p");
          System.out.println(p);
       }
    
       private Person() {
       }
    
       static {
          Person var0 = new Person();
          INSTANCE = var0;
       }
    }
    
    

    伴生对象

    fun main(args: Array<String>) {
        Person.testStatic()
        println(Person.NAME)
    }
    
    class Person {
        companion object {
            val NAME: String = "LISI"
            fun testStatic() {
                println("static")
            }
        }
    }
    

    可以理解为java中的static属性和static方法。

    定义数据类

    fun main(args: Array<String>) {
        val person = Person("lisi", 23)
        println(person) //Person(name=lisi, age=23)
    }
    data class Person(var name: String, var age: Int) {
    }
    

    kotlin为数据类默认创建equals(),hashCode(),toString(),copy(),componentN()等方法,
    类似于java中普通数据类,仅用来保存数据,没有额外的功能,java中使用lombok组件也可以达到此效果。
    反编译结果为

    点击查看代码
    public final class Person {
       @NotNull
       private String name;
       private int age;
    
       @NotNull
       public final String getName() {
          return this.name;
       }
    
       public final void setName(@NotNull String var1) {
          Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
          this.name = var1;
       }
    
       public final int getAge() {
          return this.age;
       }
    
       public final void setAge(int var1) {
          this.age = var1;
       }
    
       public Person(@NotNull String name, int age) {
          Intrinsics.checkParameterIsNotNull(name, "name");
          super();
          this.name = name;
          this.age = age;
       }
    
       @NotNull
       public final String component1() {
          return this.name;
       }
    
       public final int component2() {
          return this.age;
       }
    
       @NotNull
       public final Person copy(@NotNull String name, int age) {
          Intrinsics.checkParameterIsNotNull(name, "name");
          return new Person(name, age);
       }
    
       // $FF: synthetic method
       @NotNull
       public static Person copy$default(Person var0, String var1, int var2, int var3, Object var4) {
          if ((var3 & 1) != 0) {
             var1 = var0.name;
          }
    
          if ((var3 & 2) != 0) {
             var2 = var0.age;
          }
    
          return var0.copy(var1, var2);
       }
    
       @NotNull
       public String toString() {
          return "Person(name=" + this.name + ", age=" + this.age + ")";
       }
    
       public int hashCode() {
          String var10000 = this.name;
          return (var10000 != null ? var10000.hashCode() : 0) * 31 + this.age;
       }
    
       public boolean equals(@Nullable Object var1) {
          if (this != var1) {
             if (var1 instanceof Person) {
                Person var2 = (Person)var1;
                if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age) {
                   return true;
                }
             }
    
             return false;
          } else {
             return true;
          }
       }
    }
    

    解构赋值

    fun main(args: Array<String>) {
        val (name, age) = Person("lisi", 23)
        println("$name,$age")//lisi,23
    }
    data class Person(var name: String, var age: Int) {
    }
    

    会依次调动数据类的componentN()方法赋值给左边变量

    定义密封类

    fun main(args: Array<String>) {
        println(calc(1, 2, Add()))
        println(calc(1, 2, Sub()))
    }
    
    fun calc(a: Int, b: Int, oper: Calculator): Int {
        return when (oper) {
            is Add -> a + b
            is Sub -> a - b
        }
    }
    // 密封类
    sealed class Calculator
    
    class Add : Calculator()
    class Sub : Calculator()
    

    密封类用来表示受限的类继承结构,如例子中的,编译器知道密封类Calculator只有两个子类Add和Sub,被可能还有其他的子类,所以在when表达式中就不需要else语句了。

    泛型

    fun main(args: Array<String>) {
        val wrapper = Wrapper("hello")
        println(wrapper.item)
        Person().save(123)
    }
    // 泛型类
    class Wrapper<T>(var item: T) {
    }
    // 泛型方法
    class Person {
        fun <T> save(item: T) {
            println(item)
        }
    }
    

    更多关于kotlin中的泛型知识,如协变和逆变等,可以查看官方文档

    参考

    Kotlin 教程
    学习 Kotlin

  • 相关阅读:
    基础总结篇之三:Activity的task相关
    基础总结篇之一:Activity生命周期
    基础总结篇之二:Activity的四种launchMode
    SAP_清除默认Action
    FICO_Delete error message
    FICO_无法生成凭证(System status CLSD is active (WBS K/A6020372-205-KCCL))
    FICO_导出8月KOB3报表
    FICO_更改BP
    FICO_月末关帐
    SAP_清除默认导出格式
  • 原文地址:https://www.cnblogs.com/strongmore/p/16321463.html
Copyright © 2020-2023  润新知