文章目录
- 面向对象
- 封装
- 继承
- 多态
- 主构造函数和次构造函数
面向对象
fun main(args: Array<String>) {
var rect01 = Rect(20,10)
println("矩形的宽度:"+rect01.width+",矩形的高度:"+rect01.height)
}
class Rect(var width:Int,var height:Int)
fun main(args: Array<String>) {
var rect01 = Rect(20,10)
rect01.area()
rect01.circu()
}
class Rect(var width:Int,var height:Int){
fun area(){
println("矩形的面积:"+width*height)
}
fun circu(){
println("矩形的周长::"+(width+height)*2)
}
}
静态行为,动态方法
这里静态的是这个长方形的属性,长和宽
这里动态的是这个长方形的方法,获取面积和获取周长的方法
封装
我们再来举个栗子,洗衣机的栗子
新建一个class文件WashMachine
class WashMachine(var module:String,var size:Int) {
var isDoorOpen = true
var currentMode = 0
fun openDoor(){
println("洗衣机的门打开了")
isDoorOpen = true
}
fun closeDoor(){
println("洗衣机的门关闭了")
isDoorOpen = false
}
fun selectMode(mode:Int){
currentMode = mode
when(mode){
0 -> println("初始模式,请选择模式")
1 -> println("消毒洗")
2 -> println("棉麻洗")
else -> println("进入了奇怪模式")
}
}
fun start(){
if(isDoorOpen){
println("嘀嘀嘀门还没关,不能运行")
}else{
when(currentMode){
0 -> {println("选择模式错误,不能运行")}
1 -> {
println("进入消毒洗,高温")
setMotorSpeed(100)
}
2 -> {
println("进入棉麻洗,轻柔")
setMotorSpeed(200)
}
}
println("洗衣服开始")
}
}
//私有,只有这个类中能调用
private fun setMotorSpeed(speed:Int){
println("当前发动机转速${speed}圈/秒")
}
}
fun main(args: Array<String>) {
var washMachine = WashMachine("小天鹅",12);
washMachine.openDoor()
washMachine.closeDoor()
washMachine.selectMode(1)
washMachine.start()
}
继承
在 Kotlin 中任何一个非抽象类默认都是不可以被继承的(抽象类本身无法创建实例,一定要由子类继承它才能创建实例),相当于给 Java 中给类声明了 final,好的编程习惯是如果一个类不是专门为继承而设计的,那么就应该主动将它加上 final
声明,禁止它可以被继承
新建一个Father类,如果想被继承需要加open
关键字
open class Father {
var character:String = "性格外向"
fun action(){
println("喜欢在公共场合唱歌");
}
}
新建一个Son类继承Father类,可以发现 Father 后有一对括号,这就涉及到 Java 继承特性中的一个规定:子类总的构造函数必须调用父类中的构造函数,这个规定 Kotlin 中也要遵守。子类中的主构造函数调用父类中的哪个构造函数,在继承的时候通过括号来指定
Father 类后一对空括号表示 Son 类的主构造函数在初始化的时候会调用 Father 类的无参构造函数,即使在无参数情况下,括号也不能省略
class Son : Father() {
}
测试下
fun main(args: Array<String>) {
var son = Son()
println(son.character)
son.action()
}
查看运行结果
我们来试下重写父类方法
class Son : Father() {
override fun action(){
println("喜欢在公共场合跳舞")
}
}
查看执行结果
多态
创建一个抽象的人类
/*
* 抽象的人类
*/
abstract class Human(var name:String) {
abstract fun eat()
}
创建男人类
class Man(name:String):Human(name) {
override fun eat(){
println("${name}喜欢吃鸡腿")
}
}
创建女人类
class Woman(name:String):Human(name) {
override fun eat(){
println("${name}喜欢吃鸭脖")
}
}
编写测试代码
fun main(args: Array<String>) {
var man = Man("赵四")
man.eat()
var woman = Woman("李小花")
woman.eat()
}
查看测试结果
我们给Human再增加一个方法love
/*
* 抽象的人类
*/
abstract class Human(var name:String) {
abstract fun eat()
abstract fun love()
}
Man和Woman都需要重写这个方法
class Man(name:String):Human(name) {
......
override fun love(){
println("${name}爱买游戏")
}
}
class Woman(name:String):Human(name) {
......
override fun love(){
println("${name}爱买面膜")
}
}
编写测试代码
fun main(args: Array<String>) {
var man1 = Man("赵四")
var woman1 = Woman("李小花")
var man2 = Man("刘能")
var woman2 = Woman("王大花")
var humanList = listOf<Human>(man1,woman1,man2,woman2)
for(h in humanList){
h.love()
}
}
查看运行结果
主构造函数和次构造函数
Kotlin 将构造函数分成了两种:主构造函数和次构造函数
每个类都默认有一个不带参数的主构造函数,当然你也可以显式地给它指明参数。主构造函数特点是没有函数体,直接定义在类名后面即可。例如上面的洗衣机类 WashMachine 就将两个字段放到了主构造函数中了
由于构造函数中的参数是在创建实例的时候传入的,因此我们可以将参数声明成 val
Kotlin 为我们提供了一个 init
结构体,所有主函数中的逻辑都可以写在这里,绝大多数情况下我们不需要写 init
结构体的
class WashMachine(var module:String,var size:Int) {
var isDoorOpen = true
var currentMode = 0
init{
println("module:"+module)
print("size:"+size)
}
......
}
如果 将 Father 类改造下
open class Father(character:String,like:String) {
...
}
那么 Son 类一定会报错,以为要给 Father 传入两个参数,而 Son 类中没有,所以得增加如下
class Son(character:String,like:String) : Father(character,like) {
}
在 Son 类主构造函数增加 character 和 like 时,不能声明成 val
,因为在主构造函数中声明成 val
或 var
的参数将自动成为该类的字段,会导致和父类同名字段冲突
任何一个类只能有一个主构造函数,但可以有多个次构造函数,次构造函数通过constructor
来定义。Kotlin 规定当一个类既有主构造函数,又有次构造函数时,所有次构造函数必须调用主构造函数(包括间接调用)
class Son(character:String,like:String) : Father(character,like) {
constructor(character: String):this("","")
constructor():this("")
}
于是我们有3种方式对 Son 实例化
val son1 = Son();
val son2 = Son("性格内向");
val son3 = Son("性格内向","喜欢运动");
还有一种非常特殊的情况:类中只有次构造函数,没有主构造函数。当一个类中没有显式地定义主构造函数且定义了次构造函数,它就是没有主构造函数的
class Son: Father{
constructor(character: String,like:String):super(character,like)
}
Son 是没有主构造函数的,继承 Father 类时也就不需要加括号了。由于没有主构造函数,次构造函数只能调用父类的构造函数,所以用了 super 关键字