关键词:
类
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)... 查看详情