Kotlin笔记四,类和继承

Kotlin 中使用关键字 class 声明类

class Animal {
    
}

类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头与类体都是可选的;
如果一个类没有类体,可以省略花括号。

class Animal

构造函数

在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。

主构造函数

主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后。

class Man constructor(name: String){
}

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

class Man (name: String){
}
可见性修饰符

Kotlin 中有这四个可见性修饰符:private、 protected、 internal 和 public。
如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面:

class Man public constructor(name: String){
}

函数、属性和类、对象和接口可以在顶层声明,即直接在包内

如果你不指定任何可见性修饰符,默认为 public,这意味着你的声明将随处可见;
如果你声明为 private,它只会在声明它的文件内可见;
如果你声明为 internal,它会在相同模块内随处可见;
protected 不适用于顶层声明。

对于类内部声明的成员:

private   意味着只在这个类内部(包含其所有成员)可见;
protected 和 private一样 + 在子类中可见。
internal  能见到类声明的 本模块内 的任何客户端都可见其 internal 成员;
public 	  能见到类声明的任何客户端都可见其 public 成员。

初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。

	class Animal {
		var name :String = ""

		init {
			println("This is animal!")

			name = "动物"
		}
	}

	var animal = Animal()
	println("Animal ---"+animal.name)
	
	//This is animal!
	//Animal ---动物

可以写多个init{},会按顺序执行

次构造函数

类也可以声明前缀有 constructor的次构造函数:

class Man {
	var name :String = ""
	var age :Int? = null
	var score :Int? = null
	init {
		println("init ---")
	}

	constructor(name :String){
		println("name --- $name")
		this.name = name
	}

	constructor(name :String,age :Int){
		println("name ---$name   ----  age : $age")
		this.name = name
		this.age = age
	}
	constructor(name :String,age :Int,score :Int){
		println("name ---$name   ----  age : $age  -----  score : $score")
		this.name = name
		this.age = age
		this.score = score
	}
}

    val man  = Man("辩护人")
    val xiuMan = Man("泰秀",18)
    val zhongMan = Man("一中",18,88)
	
	输出
	
	System.out: init ---
	System.out: name --- 辩护人
	System.out: init ---
	System.out: name ---泰秀   ----  age : 18
	System.out: init ---
	System.out: name ---一中   ----  age : 18  -----  score : 88

init {}代码块会优先于次构造函数执行

创建类的实例

直接调用构造函数即可。Kotlin 中没有 new 关键字

val man  = Man("辩护人")

继承

在 Kotlin 中所有类都有一个共同的超类 Any,这对于没有超类型声明的类是默认超类:

class Example {
}       //从 Any 隐式继承

Any 有三个方法:equals()、 hashCode() 与 toString()

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 */
public open class Any {
	/**
	 * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following
	 * requirements:
	 *
	 * * Reflexive: for any non-null reference value x, x.equals(x) should return true.
	 * * Symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
	 * * Transitive:  for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true
	 * * Consistent:  for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
	 *
	 * Note that the `==` operator in Kotlin code is translated into a call to [equals] when objects on both sides of the
	 * operator are not null.
	 */
	public open operator fun equals(other: Any?): Boolean

	/**
	 * Returns a hash code value for the object.  The general contract of hashCode is:
	 *
	 * * Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
	 * * If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result.
	 */
	public open fun hashCode(): Int

	/**
	 * Returns a string representation of the object.
	 */
	public open fun toString(): String
}

声明一个显式的超类型,在类头中把超类型放到冒号之后即可:

如果派生类有一个主构造函数,其基类型必须用基类的主构造函数参数就地初始化。

open class An(
    var name :String
)
class Person(name: String):An(name)

如果派生类没有主构造函数,那么每个次构造函数必须使用 super 关键字初始化其基类型,

class CustomView : View {
	constructor(context : Context): super(context)
	constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
	constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
}
覆盖方法

对于可覆盖的成员(我们称之为开放)以及覆盖后的成员需要显式修饰符:

open class Animal(){
	open fun run(){

	}
	fun eat(){
 
	}
}

class Horse() : Animal() {
	override fun run() {

	}
}

Horse.run() 函数上必须加上 override 修饰符。不加会报错。
eat()方法子类不可以重写。

open 修饰符对添加了final的类不起作用。

派生类中的代码可以使用 super 关键字调用其超类的函数与属性访问器的实现:

open class Animal(){
	open fun run(){

	}

	fun eat(){

	}
	open var total : Int = 100;

	var age :Int = 18
}


class Horse() : Animal() {
	override fun run() {
		 super.run()
	}

	override var total = 99

	
    var  horseAge = super.age

}
覆盖规则

如果一个类从它的直接超类继承相同成员的多个实现, 它必须覆盖这个成员并提供其自己的实现。
为了表示采用从哪个超类型继承的实现,我们使用由尖括号中超类型名限定的 super:

open class Pen(){
	open fun draw(){

	}
}
//接口成员默认就是“open”的
interface ColourPen{
	fun draw(){

	}
}

class Paper() : Pen(),ColourPen{

	override fun draw() {
		super<Pen>.draw()   //调用 Pen.draw()
		super<ColourPen>.draw()   //调用 ColourPen.draw()
	}
}
抽象类

类以及其中的某些成员可以声明为 abstract。
可以用一个抽象成员覆盖一个非抽象的开放成员。

open class Pen(){
	open fun draw(){

	}
}
abstract class BrushPen : Pen(){
	abstract override  fun draw()
}

派生类继承时必须重写draw()方法
class BlackPen : BrushPen(){
	override fun draw() {

	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章