ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Kotlin学习之面向对象

2022-06-01 18:32:04  阅读:176  来源: 互联网

标签:name 面向对象 Kotlin age 学习 Person fun println String


定义普通类

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

标签:name,面向对象,Kotlin,age,学习,Person,fun,println,String
来源: https://www.cnblogs.com/strongmore/p/16321463.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有