面向对象
我们都知道Java是面向对象语言,Kotlin同样是面向对象语言,面向对象有三大特性五大原则,先复习一下什么是面向对象的三大特性:
- 封装(Encapsulation)
封装,就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
封装的优点:
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
- 继承
继承,指可以让某个类型的对象获得另一个类型的对象的属性的方法。
继承的特性
1. 子类:
通过继承创建的新类,也叫“派生类”;
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展;
子类拥有父类非private的属性,方法;
子类可以用自己的方式实现父类的方法。
2. 父类:被继承的类,也叫“超类”、“基类”
继承概念的实现方式有二类:实现继承与接口继承。
实现继承:是指直接使用基类的属性和方法而无需额外编码的能力,实现继承只支持单继承;
接口继承:是指仅使用属性和方法的名称、但是子类必须提供实现的能力,接口继承支持多继承。
- 多态
多态,是指一个类实例的相同方法在不同情形有不同表现形式。
多态的优点
1. 消除类型之间的耦合关系
2. 可替换性
3. 可扩充性
4. 接口性
5. 灵活性
6. 简化性
多态存在的三个必要条件
1. 继承
2. 重写
3. 父类引用指向子类对象
Kotlin面向对象使用
类的定义
- 无参类的定义
class EmptyClass
fun main(args:Array<String>){
var ec = EmptyClass() //kotlin创建对象不需要new
println(ec.toString())//调用类的toString()方法
println(ec::class) //::表示将class方法传入一个方法中当参数
println(ec is EmptyClass)//判断类的归属
}
输出结果:
EmptyClass@27c170f0
class EmptyClass
true
- 带参类的定义
class Student{
var name:String
var score:Int = 60 //Int类型必须有初始化值
var cls:Int = 3
constructor(name: String, score: Int, cls: Int){
this.name = name
this.score = score
this.cls = cls
}
override fun toString(): String {
return "Student(name='$name', score=$score, cls=$cls)"
}
}
fun main(args:Array<String>){
var student = Student("name",32,34)
println(student.toString())
}
结果输出:
Student(name='name', score=32, cls=34)
我们也可以在声明类的同时声明构造函数:
class Teacher(name:String,age:Int){
var mName = name;
var mAge = age;
override fun toString(): String {
return "name = ${mName} and age = ${mAge}"
}
}
fun main(args:Array<String>){
var teacher = Teacher("ailian",32)
println(teacher.toString())
}
还有一种办法可以不创建属性mName/mAge,而是在构造参数前添加var
class Teacher(var name:String, var age:Int){
override fun toString(): String {
return "name = ${name} and age = ${age}"
}
}
fun main(args:Array<String>){
var teacher = Teacher("ailian",32)
println(teacher.toString())
}
以上两种方式输出结果一样:
name = ailian and age = 32
我们也可以IDEA工具自带的方法生成各种构造函数:
Kotlin类的继承
Kotlin使用:表示继承关系,比如:
abstract class Animal{//定义一个抽象类
abstract var name:String//抽象类的属性必须是抽象的
abstract var age:Int
abstract fun cry():Boolean//定义抽象方法
/**
* 定义一个普通方法、Unit表示无需返回值
* 默认是final,不可以覆写
*/
fun smile():Unit{
"haha..."
}
/**
* 定义一个可以覆写的普通方法
*/
open fun call():Unit{
"haha..."
}
}
class Dog(override var name: String, override var age: Int):Animal(){//override:覆写属性,Cat继承Animal,并实现抽象方法
override fun cry(): Boolean { //实现方法
println("${name} is cry...")
return true
}
override fun call() {
super.call()
println("${name} is call...")
}
}
class Pig: Animal() {
override var name: String = ""
override var age: Int = 0
override fun cry(): Boolean {
println("${name} is cry... age is ${age}")
return true
}
}
fun main(args:Array<String>):Unit{
var pig = Pig()
pig.name = "Peppa"
pig.age = 4
println(pig.cry())
var dog = Dog("dahuang",3)
println(dog.call())
println(dog.cry())
}
结果输出:
Peppa is cry... age is 4
true
dahuang is call...
kotlin.Unit
dahuang is cry...
true
Kotlin接口
Kotlin和Java一样,不支持同时继承多个父类,也就是说继承只能存在一个父类。但是一个类可以同时实现多个接口。
Kotlin的接口和Java只能有抽象方法不同,Kotlin的接口可以有抽象的方法和实现的方法:
接口没有构造函数,接口的实现和继承一样使用冒号: 实现多个接口用,逗号隔开:
/**
* 定义一个Animal接口
*/
interface Animal {
var name: String
var age: Int
fun cry()
fun smile() {
println("I am smile ... ")
}
}
/**
* 定义一个Action接口
*/
interface Action {
}
/**
* 创建一个Pig类并实现Animal和Action接口
*/
class Pig(override var name: String, override var age: Int) : Animal,Action{
override fun cry() {
println("${name} is cry ... ")
}
}
/**
* 用另一种形式创建一个类Dog并实现Animal和Action接口
*/
class Dog:Animal,Action{
override var name: String =""
override var age: Int = 0
override fun cry() {
println("${name} is cry ... ")
}
}
fun main(args:Array<String>):Unit{
var pig = Pig("Peppa",2)
println(pig.cry())
var dog = Dog()
dog.name = "xiaowang"
dog.age = 3
println(dog.cry())
}
结果输出:
Peppa is cry ...
kotlin.Unit
xiaowang is cry ...
kotlin.Unit
Kotlin内部类的使用
内部类就是在类中创建类,Kotlin中可以无限嵌套内部类
内部类分为:普通内部类、匿名内部类
class InnerClass{
class InnerClass1{
var name:String = "inner1"
class InnerClass2{
var age:Int = 0
fun innerfun2(){
/**
* 这里不能直接使用InnerClass1的成员变量name,需要通过创建InnerClass1引用后调用
*/
println("InnerClass name = ${InnerClass.InnerClass1().name}")
}
class InnerClass3{
fun innerfun3(){
/**
* //创建最终需要使用方法的对象
*/
InnerClass.InnerClass1.InnerClass2().innerfun2();
}
}
/**
* 使用inner class 可以直接使用外部类InnerClass2的成员变量
* 这里并不能引用InnerClass1的name属性,应为InnerClass2未使用inner修饰
*/
inner class InnerClass4{
fun innerfun4(){
age = 3
println("InnerClass4 = ${age}")
}
}
fun run(){
Thread(object :Runnable {
override fun run(){
println("i am a anonymous class")
}
}).start()
}
}
}
}
fun main(args:Array<String>){
InnerClass.InnerClass1.InnerClass2().innerfun2()
InnerClass.InnerClass1.InnerClass2.InnerClass3().innerfun3()//
InnerClass.InnerClass1.InnerClass2().run()
/**
* 注意对比改调用方法与上面三种调用方法的区别
*/
InnerClass.InnerClass1.InnerClass2().InnerClass4().innerfun4()//
}
结果输出:
InnerClass name = inner1
InnerClass4 = inner1
i am a anonymous class
InnerClass1 = 3
Kotlin中的单列模式
Kotlin中没有静态属性和方法,可以使用关键字 object 声明一个object 单例对象:
object SingleClass{
var name:String = "single"
var age:Int = 18
fun hello(){
println("Hello World ... ")
}
}
class CompanionClass {
/**
* 通过 companion object 定义一个伴生对象,可以直接使用Class.fun直接调用
* 一个类只能有一个伴生对象
*/
companion object CompanionClass1 {
fun compan() {
println("I am companion object ...")
}
fun compan2(){
println("I am companion2 object ...")
}
}
}
fun main(args:Array<String>){
println("name = ${SingleClass.name} and age = ${SingleClass.age}")
SingleClass.hello()
/**
* 伴生类的调用
*/
CompanionClass.compan()
CompanionClass.compan2()
}
结果输出:
name = single and age = 18
Hello World ...
I am companion object ...