zoukankan      html  css  js  c++  java
  • Kotlin学习快速入门(3)——类 继承 接口

    参考链接

    类定义格式

    使用class关键字定义,格式如下:

    class T{
    	//属性
    	//构造函数
    	//函数
    	//内部类
    }
    

    Java Bean类

    java bean类

    //java bean类
    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name) {
            this.name = name;
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    java bean类(kotlin实现)

    //kotlin写法,get和set方法默认实现
    class Student {
    	/注意,这里的var代表着变量的数值之后可以被修改,也可以使用只读val
    	//?是可为空的写法,后面会提到
    	//这里其实包含了主构造方法,不过因为主构造方法为空,所以省略了
        var name: String? = null
        var age: Int = 0
    
    	//这几个constructor是次级构造方法
        constructor() {}
    
        constructor(name: String) {
            this.name = name
        }
    
        constructor(name: String, age: Int) {
            this.name = name
            this.age = age
        }
        
    }
    
    //下面是没有省略主构造方法的
    //注意,因为把默认的主构造方法写了出来,所以,不允许出现无参数的次构造方法
    class Student public constructor() {
        //注意,这里的var代表着变量的数值之后可以被修改,也可以使用只读val
        //?是可为空的写法,后面会提到
        //这里其实包含了主构造方法,不过因为主构造方法为空,所以省略了
        var name: String? = null
        var age: Int = 0
    
        //这几个constructor是次级构造方法
        constructor(name: String) : this() {
            this.name = name
        }
    
        constructor(name: String, age: Int)  : this(){
            this.name = name
            this.age = age
        }
    }
    
    

    主函数调用

    //主函数调用
    fun main(args: Array<String>){
    	//声明类不需要new关键字
    	val student = Student("star",12)
    	//,使用对象.属性名调用,而不是使用get或set
    	println(student.age)//获得属性
    	student.name = "stars"//修改属性
    }
    

    主构造方法(kotlin)

    kotlin类中可以有主构造方法和次构造方法,次构造方法也就是上面那段使用kotlin实现的Java Bean类(上面的主构造方法其实是省略了的)

    /*下面三种方法都是声明了一个Student类
    *Student包含了一个构造方法(两个参数),还有两个成员变量以及成员变量对应的get和set方法
    */
    
    //原始方式,使用主构造方法
    class Student public constructor(name: String,age: Int) {
    	//注意,这里的var代表着变量的数值之后可以被修改,也可以使用只读val
        var name = name
        var age = age
    }
    
    //简洁写法,如果主构造方法只有默认的修饰符(public,默认的修饰符可省略),可以把constructor省略
    class Student(name: String,age: Int) {
        var name = name
        var age = age
    }
    
    //更简洁写法
    class Student(var name: String,var age: Int) {
    }
    
    //使用Student类
    fun main(args: Array<String>) {
    	//声明类不需要new关键字
        val student = Student("star",12)
        println(student.name)
        println(student.age)
    	student.age = 19 //修改内容
    	println(student.age)
    }
    
    

    init(初始化块)

    如果我们想要在主构造方法进行初始化操作,需要在init代码块里面写我们的代码,如

    //更简洁写法
    class Student(var name: String,var age: Int) {
    	init{
    		println("这里是初始化操作")
    	}
    }
    

    注意,初始化块是主构造方法的一部分

    初始化操作会在次构造方法之前执行,即使没有写主构造方法,如:

    class Student{
    	var name: String? = null
    	var age: Int = 0
    	
    	init{
    		println("这里是初始化操作")
    	}
    	
    	constructor(name: String, age: Int) {
    		this.name = name
    		this.age = age
    	}
    }
    

    主/次构造方法联合使用

    类定义了主构造器,次构造器必须直接或间接调用主构造器;

    class Student() {
        var name: String? = null
        var age: Int = 0
    
        //这几个constructor是次级构造方法,,这里的this()就是当前的主构造方法
        constructor(name: String) : this() {
            this.name = name
        }
    
        constructor(name: String, age: Int)  : this(){
            this.name = name
            this.age = age
        }
    }
    
    class Student public constructor() {
        var name: String? = null
        var age: Int = 0
    
        //这几个constructor是次级构造方法,,这里的this()就是当前的主构造方法
    	//这里用专业术语说,是次级构造方法需要委托给主构造方法
        constructor(name: String) : this() {
            this.name = name
        }
    
        constructor(name: String, age: Int)  : this(){
            this.name = name
            this.age = age
        }
    }
    

    伴生方法(静态方法)

    class Student{
    	...
    	companion object {
    		@JvmStatic
    		//下面定义一些方法
    		fun sayHello() {
    			println("hello")
    		}
    	}
    }
    
    

    get/set方法修改

    看完上面,我们都知道kotlin默认帮我们实现了get和set方法,val修饰的变量是只读的,所以该变量没有setter方法

    格式:

    var <propertyName>[: <PropertyType>] [= <property_initializer>]
        [<getter>]
        [<setter>]
    //表达式写法
    get() = ...
    //花括号写法
    get(){
    	...
    	return xx
    }	
    
    class Student() {
        var name: String = ""
        var age: Int = 0
    	//这里使用val
        val isNameEmpty: Boolean
            get() = name.length==0
     
    	//使用var就得赋值
    	//val isNameEmpty: Boolean
        //    get() = name.length==0
    	
        constructor(name: String) : this() {
            this.name = name
        }
    
        constructor(name: String, age: Int)  : this(){
            this.name = name
            this.age = age
        }
    }
    

    如果要在get和set引用当前的字段(属性值),得使用filed关键字代替内容

    class Student() {
        var name: String = ""
    		//如果当前的name为"",则返回小红作为姓名
    		//这里的filed就是name,类型也与name一样
            get() {
                return if(field.length==0) "小红" else field
            }
        var age: Int = 0
    
        constructor(name: String) : this() {
            this.name = name
        }
    
        constructor(name: String, age: Int)  : this(){
            this.name = name
            this.age = age
        }
    }
    

    setter方法与之前的getter方法一样,里面也是使用field代替当前的数值,只不过setter有一个参数,默认为value,可以修改名字

    set(value){
    	filed = vaule
    }
    

    嵌套类和内部类

    嵌套类和内部类的区别是,嵌套类无法引用外层类的属性和方法,而内部类可以

    //Nested为嵌套类
    class Outer {
        private val bar: Int = 1
        class Nested {
    		//这里因为是嵌套类,无法引用Outer中的bar
            fun foo() = 2
        }
    }
    
    val demo = Outer.Nested().foo() // == 2
    

    内部类,使用inner关键字

    class Outer {
        private val bar: Int = 1
        inner class Inner {
    		//这里可以引用bar
            fun foo() = bar
        }
    }
    
    val demo = Outer().Inner().foo() // == 1
    

    继承和接口

    继承

    kotlin所有的类都是继承于Any,注意,Any 并不是 java.lang.Object

    kotlin中的类默认是不可继承的,需要有open关键字修饰类,需要在子类复写的方法,也得在父类用open修饰该方法

    open class Person{
        var name: String = ""
        var age: Int =0
        
        constructor(){}
        constructor(name: String, age: Int){
            this.name = name
            this.age = age
        }
    
        open fun hello() {
            println("hello this is person")
        }
    }
    
    class Student: Person {
    	constructor() : super(){}
        constructor(name: String,age: Int) :super(name,age){}
    
        override fun hello() {
            println("hello this is student")
        }
    }
    
    

    接口

    接口的实现也是使用:,声明接口也是interface关键字,注意,kotlin中的接口方法可以实现

    interface Print {
        fun print()
        fun say(){
            println("sayhello")
        }
    }
    

    Student类继承Person并实现Print接口:

    class Student: Person,Print {
        override fun print() {
            //复写接口里的方法
        }
    
        constructor(name: String,age: Int) :super(name,age){}
    
        override fun hello() {
    
        }
    }
    

    数据类

    介绍

    kotlin提供了一个数据类,专门类存放数据,使用关键字data修饰类

    官方的关于数据类的规范:

    • 主构造函数需要至少有一个参数;
    • 主构造函数的所有参数需要标记为 val 或 var;
    • 数据类不能是抽象、开放、密封或者内部的;
    • (在1.1之前)数据类只能实现接口。

    数据类主要有下面两种特点:

    • 自动解析
    • 直接复制

    数据类定义

    data class Person(var name: String,var age: Int){
    }
    

    解构

    解构有顺序,顺序根据类中属性的属性

    kotlin1.1开始支持使用"_"跳过不需要的变量

    val person = Person("star",19)
    //val括号里可以根据需要选择不同参数,注意顺序
    val(name,age) = person
    println("$name, $age years of age") // 输出 "star, 19 years of age"
    //跳过name
    val(_,age) = person
    println(age)
    

    复制

    val person = Person("star",19)
    val person1 = person.copy()
    //复制并修改部分属性
    val person2 = person.copy(age =23)
    

    总结

    个人觉得,如果某个类只有一个构造方法,可以定义类只含有一个主构造方法即可,使用那个最简洁的方式。

    如果需要有不同参数的构造方法(或者是Java Bean),则使用次级构造方法

    如果是用来当做数据类,则使用数据类定义

  • 相关阅读:
    第一学期心得
    第十三次作业
    第十二次作业
    第十一次作业
    第十次作业
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    第五次作业
  • 原文地址:https://www.cnblogs.com/stars-one/p/11262112.html
Copyright © 2011-2022 走看看