kotlin类与继承(代码片段)

星火燎原2016 星火燎原2016     2022-12-10     413

关键词:

kotlin 中使用关键字 class 声明类

类声明由类名,类头(指定其类型参数,主构造函数等),花括号包围的类体构成,类头 和类体都是可选的。

class Student 
    

如果一个类没有类体,则可以省略花括号

class Empty 

主构造函数

一个类可以有一个主构造函数和一个或多个次构造函数,主构造函数是类头的一部分,主构造函数跟在 类名后。

class 类名 constructor(形参1,形参2,形参3
    

class Employee constructor(firstName: String, lastName: String, age: Int) 
    private var name: String
    private var firstName: String
    private var lastName: String
    private var workTime: Int

    init 
        println("first init")
        this.firstName = firstName   // 主构造函数不能包含任何初始化代码,所以放在 init 中初始化成员变量 firstName,lastName
        this.lastName = lastName
        this.name = this.firstName + this.lastName    // 成员变量可以在 init 初始化代码块中初始化
        workTime = age / 2
    

    init 
        println("second init")
    


// 输出结果:
first init
second init

注意点:

  • 关键字 constructor ,在 Java 中,构造方法名必须和类名相同,而在 kotlin 中,是通过 contructor 关键字来标明的,且对于主构造函数而言,它的位置是在 类头(即紧跟类名的后面),而不是在类体中。
  • 关键字 init : init 被称作是初始化代码块,他的作用是为主构造函数服务的,由于主构造函数是放在 类头中的,是不能包含任何初始化语句的(这是语法规定的),这个时候就是 init 的用武之地了,我们可以把初始化执行语句放在 init 代码块中进行初始化,为类的成员属性赋值。
  • 在实例初始化期间,初始化代码块按照他们出现在类体重的顺序执行,与属性初始化器交织在一起。

如果主构造函数没有任何注解或可见性修饰符,则可以省略这个 constructor 关键字。

class Employee(fristName: String, lastName: String, age: Int)  // 省略 constructor 关键字


类的成员属性初始化不是必须放在 init 代码块中的,可以在定义属性时直接将主构造函数中的形参赋值给他。

class Employee constructor(firstName: String, lastName: String, age: Int) 
    private var name: String = firstName + lastName
    private var firstName: String = firstName
    private var lastName: String = lastName
    private var workTime: Int = age / 2

    init 
        println("first init")
        this.firstName = firstName   // 主构造函数不能包含任何初始化代码,所以放在 init 中初始化成员变量 firstName,lastName
        this.lastName = lastName
        this.name = this.firstName + this.lastName    // 成员变量可以在 init 初始化代码块中初始化
        workTime = age / 2
    

    init 
        println("second init")
    

可以发现,这种在构造函数中声明形参,然后在属性定义进行赋值,有点繁琐,我们可以直接在主构造函数中定义类的属性。

class Computer(private var name: String, private var price: Int) 

    fun printInfo() 
        println("name = $name , price  = $price")
    

fun main(args: Array<String>) 
    var appleComputer = Computer("apple", 10000)
	appleComputer.printInfo()

输出结果:

name = apple , price  = 10000

当我们在定义一个类时,如果没有显式的提供主构造函数,Kotlin 编译器会默认生成一个无参主构造函数,这点和 Java 是一样的

class Mouse 
    private var name: String = "LenovoMousc"
    private var price: Int = 23
    fun printInfo() 
        println("name = $name , price = $price")
    


fun main(args: Array<String>) 
    var lenovoMouse = Mouse()
    lenovoMouse.printInfo()

输出结果:

name = LenovoMousc , price = 23

次构造函数

与主构造函数不同的是: 次构造函数是定义在类体中的,并且次构造函数可以有多个,而主构造函数只能有一个。

class MyButton : AppCompatButton 
    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, R.attr.buttonStyle)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

注意点:

  • 可以使用 this 关键字来调用 自己的其他构造函数
  • 使用 super 关键字来调用父类构造函数

我们看下,同时定义主构造函数和多个次构造函数

class Mouse(name: String, price: Int, address: String) 

    private var name: String = name
    private var price: Int = price
    private var address: String = address

    constructor(name: String) : this(name, 0)

    constructor(name: String, price: Int) : this(name, price, "")

    fun printInfo() 
        println("name = $name , price  = $price, address = $address")
    


fun main(args: Array<String>) 
    var lenovoMouse = Mouse("applemouse")
    lenovoMouse.printInfo()

一个 三个参数的主构造函数,两个次构造函数。一个参数的次构造函数调用了两个参数的次构造函数,两个参数的次构造函数调用了三个参数的主构造函数。

我们把 两个参数的次构造函数的 this(name,price,"") 删除掉,会出现什么问题呢?

class Mouse(name: String, price: Int, address: String) 

    private var name: String = name
    private var price: Int = price
    private var address: String = address

    constructor(name: String) : this(name, 0)

    constructor(name: String, price: Int)     // 删除掉调用三个参数的主构造器,会提示: Primary constructor call expected

    fun printInfo() 
        println("name = $name , price  = $price, address = $address")
    


fun main(args: Array<String>) 
    var lenovoMouse = Mouse("applemouse")
    lenovoMouse.printInfo()

删除三个参数的主构造函数会提示: Primary constructor call expected

结论:次构造函数会直接或间接调用主构造函数的

创建类的实例

要创建一个类的实例,可以普通函数一样调用 构造函数。

kotlin 中没有 new 关键字

var employee = Employee("1001", "xiaohe", 12)

类成员

类可以包含:

  • 构造函数与初始化代码块
  • 函数
  • 属性
  • 嵌套类和内部类
  • 对象声明

继承

在 kotlin 中所有类都有一个共同的超类 Any , 这对于没有声明超类型的类提供了默认的超类

注意点:

  • Kotlin 中如果类前面不加关键字 open, 则该类默认是 final 的 ,也就是不能被继承,如果继承该类,会报错: This type is final, so it cannot be inherited from.

  • Any 类 默认提供了三个方法 : equal() , hashCode() ,toString()

  • 基类中没有定义构造器时,Kotlin 会默认添加一个无参的构造器,所以子类在继承该基类时,需要实现该基类的无参构造器。

    // 编译器会提供的默认无参的构造器
    open class Phone 
    
    
    // 继承基类时,需要实现基类中的无参的构造器
    class ApplePhone(private var rom: Int) : Phone() 
    
        fun printInfo() 
            println("the rom is $rom")
        
    
    

    输出结果:

    the rom is 4
    
  • 在写子类是,如果子类中有主构造函数,那么基类必须要在主构造函数中立即初始化

    // open 标识该类可以被继承
    open class Mouse(name: String, price: Int, address: String) 
        private var name: String = name
        private var price: Int = price
        private var address: String = address
        
        constructor(name: String) : this(name, 0)
    
        constructor(name: String, price: Int) : this(name, price, "")
    
        fun printInfo() 
            println("name = $name , price  = $price, address = $address")
        
    
    
    class AppleMouse(name: String, price: Int, address: String, wireless: Boolean) : Mouse(name, price, address) 
    
    
    
  • 如果子类中没有主构造函数,那么必须要在此构造函数中调用 super 关键字初始化父类,或者调用另一个此构造函数。初始化父类时,可以调用父类的不同的构造函数。

重写

重写方法

在继承基类时,子类可以重写基类中的有 open 关键字修饰的方法,如果没有 open 修饰的方法,是允许子类重写的,重写方法时,需要使用 override 关键字标识。

在 IDEA IDE 中,在子类中可以使用快捷键 Ctrl + O 快速重写父类中被 open 关键字修饰的方法

// 基类有默认的无参构造器,所以子类继承时,
open class Phone 
    open fun getColor() 
        println("phone has many colors")
    


class ApplePhone(private var rom: Int) : Phone() 

    override fun getColor() 
        super.getColor()
        println("iPone color is red")
    

    fun printInfo() 
        println("the rom is $rom")
    


fun main(args:Array<String>) 
    var iPhone = ApplePhone(4)
    iPhone.getColor()

输出结果:

iPone color is red

如果一个类继承了多个类或接口,并且父类或接口中有相同的名字的方法需要重写,那么子类这时候必须重写该方法,并且如果子类想区分父类中的方法,可以使用 super 关键字调用不同的父类方法。

/**
 * 类中的 open 关键字标识该类可以被继承
 */
open class Fly 
    /**
     * 方法中的 open 关键字标识该方法可以被重写
     */
    open fun show() 
        println("Fly ......")
    


/**
 * interface 不用写 open, 默认就是 open 的
 */
interface Run 
    /**
     * 接口中的方法默认是 open 的
     */
    fun show() 
        println("Run .....")
    


/**
 * 子类实现接口时不用写 (), 因为接口是没有构造函数的
 */
class Bird : Fly(), Run 
    override fun show() 
        super<Fly>.show()   // 使用 super 关键字来调用不同父类中的同名方法
        super<Run>.show()
    

输出结果:

Fly ......
Run .....
重写变量
  • 基类中被重写的变量也要有 open 关键字的声明,
  • 子类可以使用 var 类型的变量去重写父类中 val 类型的变量,但是不能使用 val 类型的变量去重写父类中 var 类型的变量(如果使用 val 类型的变量去重写父类的 var 类型的变量,那么子类这个 val 类型的变量就会多一个 set 方法,而 val 类型的变量是不允许有 set 方法的)
open class Car(maxSpeed: Int, price: Int) 
    open val maxSpeed: Int = maxSpeed
    open var price: Int = price


class Maserati(maxSpeed: Int, price: Int) : Car(maxSpeed, price) 
    /**
     * 子类使用 var 类型重写父类中的 val 类型的变量
     */
    override var maxSpeed: Int = maxSpeed
    /**
     * 子类使用 val 类型重写父类中的 var 类型的变量,========>>>>>>编译报错
     */
    override val price: Int = price

kotlin快速入门:基础语法类与继承集合(代码片段)

参考书籍:《AtomicKotlin》,全英文,读起来慢,但是写得很详细,没有任何语言基础的也能看懂《第一行代码Android第三版》,第二章,有java基础的看一看就会了Kotlin中文文档,很详细,可以当... 查看详情

kotlin数据类与密封类(代码片段)

/***主构造函数至少包含一个参数*所有的主构造函数的参数必须标识为val或者var*数据类不可以声明为abstractopen、sealed或者inner*数据类不能继承其他类,但是可以实现接口*///关键字为datadataclassUser(valname:String,valage:Int)//funcopy(name:Str... 查看详情

kotlin类与继承

类Kotlin使用class关键字声明类,类声明由类名、类头(指定其类型参数、主构造函数等)和由大括号包围的类体组成。类头和类体都是可选的,如果一个类没有类体大括号可省略class NoBody类的构造函数一类可以有一个主构造... 查看详情

kotlin学习之类与对象继承与构造函数(代码片段)

类与对象首先创建一个Person类。右击包→New→KotlinFile/Class,在弹出的对话框中输入“Person”。对话框在默认情况下自动选中的是创建一个File,File通常是用于编写Kotlin顶层函数和扩展函数的,我们可以点击展开下拉列... 查看详情

kotlin数据类与密封类(代码片段)

数据类Kotlin可以创建一个只包含数据的类,关键字为 data:dataclassUser(valname:String,valage:Int)编译器会自动的从主构造函数中根据所有声明的属性提取以下函数:equals() / hashCode()toString() 格式如 "User(name=John,age=42)"co... 查看详情

kotlin开发基础(代码片段)

...一时间获取我的最新文章,请关注公众号:技术特工队Kotlin开发基础(一)Kotlin开发基础(二)Kotlin开发基础(三)类本篇文章主要介绍类的继承,接口,复写,单例,以及object属性的介... 查看详情

kotlin内部类与嵌套类(代码片段)

kotlin内部类与嵌套类简单的说,kotlin嵌套类相当于java的静态内部类,kotlin内部类相当于java普通内部类。classOutClassvalocval="一个外部类变量值"//嵌套类,相当于Java的静态内部类classNestedClassfuntest1()="嵌套... 查看详情

kotlin内部类与嵌套类(代码片段)

kotlin内部类与嵌套类简单的说,kotlin嵌套类相当于java的静态内部类,kotlin内部类相当于java普通内部类。classOutClassvalocval="一个外部类变量值"//嵌套类,相当于Java的静态内部类classNestedClassfuntest1()="嵌套... 查看详情

kotlin学习——基础巩固,类与继承,lambda,表达式,计算器

一.类与继承我们沿用Java的经典案例,人,男人,女人,首先,我们如果要创建一个类,他为男人,他具有姓名,年龄,身高的属性,我们要创建女人,他也有这些属性,但是他们都... 查看详情

java学习笔记3(datawhale教程)(代码片段)

java学习笔记3(datawhale教程):类与方法,继承与多态,抽象类与接口文章目录java学习笔记3(datawhale教程):类与方法,继承与多态,抽象类与接口一.类与方法1.类与对象2.成员变量3.成员方法语法格式来看例子成员方法的参数值参数引用参数... 查看详情

继承和派生——类与类之间的关系继承的基本概念(代码片段)

1、类与类之间的关系  has-A,uses-A和is-A  has-A包含关系,用以描述一个类由多个“部件类”构成。实现has-A关系用类成员表示,即一个类中的数据成员是另一种已经定义的类。  uses-A一个类部分地使用另一个类。通过类之... 查看详情

kotlin学习之路:继承(代码片段)

...承二.继承中的构造函数2.1继承中Java的构造函数2.2继承中Kotlin的构造函数2.3Kotlin多个构造函数的情况三.重写和重载3.1方法的重写3.2属性的重写四.super关键字4.1简单用法4.2复杂情况下的用法4.2.1子类重写方法中使用super4.2.2子类选择... 查看详情

python基础学习第十五节类与继承(类与继承,这一篇就足够了)(代码片段)

Python基础学习之类与继承1.面向对象名词解释类(Class):用来描述具有相同的属性和方法的对象的集合。类中定义了类对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数,被称为:方法。属性:类中的类变量,我... 查看详情

经典类与新式类的继承顺序(代码片段)

1#经典类与新式类的继承顺序23classTeacher(object):4cn=‘Harvard‘5def__init__(self,name,age,sex):6self.name=name7self.age=age8self.sex=sex9self.__money=56001011defshow_private_attribule(self):12print(‘privateattribu 查看详情

记录python类与继承的一个错误(代码片段)

今天在学python的类与继承的时候遇到一个错误,原来是自己在ctrl+c ctrl+v的时候漏了一个括号1classCar():2def__init__(self,make,year,model):3self.make=make4self.model=model5self.year=year6self.odometer_reading=07defget_descriptive_name 查看详情

kotlin小悟-这个继承有点不一样(代码片段)

今天聊聊kotlin中关于构造函数的一个话题。我们知道,在kotlin中构造函数分为主构造函数和从构造函数,关于详细的内容,可以点击下面的文章链接了解。Kotlin系列之主构造方法和初始化语句块Kotlin系列之从构造方法... 查看详情

typescript-4.es5与typescript的类与继承(代码片段)

ES5中的类与类的继承(1)简单的类functionPerson()this.name='张三';this.age=20;varp=newPerson();alert(p.name);(2)构造函数和原型链里面增加方法functionPerson()this.name='张三';/*属性*/this.age=20;this.run=function()ale 查看详情

kotlin学习——数据类,泛型,嵌套类与内部类,对象表达式和对象声明(代码片段)

一.数据类数据类和JAVA中的javabean类似,只作用于保存一些数据,所以如果创建,会默认生成一些函数,并且会被标记为data:equals()/hashCode()toString()componentN()copy()我们来看下标准的写法dataclassUser(valname:String,valage:Int)... 查看详情