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() {

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