Kotlin自學日記之接口和抽象類的區別(上)

  • 接口 Interface
  • 抽象類 abstract

如何區分接口和抽象類?
以下內容轉自:https://www.cnblogs.com/yongjiapei/p/5494894.html
1、抽象類和接口都不能直接實例化,如果要實例化,抽象類變量必須指向實現所有抽象方法的子類對象,接口變量必須指向實現所有接口方法的類對象。
2、抽象類要被子類繼承,接口要被類實現。
3、接口只能做方法申明,抽象類中可以做方法申明,也可以做方法實現
4、接口裏定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。
5、抽象類裏的抽象方法必須全部被子類所實現,如果子類不能全部實現父類抽象方法,那麼該子類只能是抽象類。同樣,一個實現接口的時候,如不能全部實現接口方法,那麼該類也只能爲抽象類。
6、抽象方法只能申明,不能實現,接口是設計的結果 ,抽象類是重構的結果
7、抽象類裏可以沒有抽象方法
8、如果一個類裏有抽象方法,那麼這個類只能是抽象類
9、抽象方法要被實現,所以不能是靜態的,也不能是私有的。
10、接口可繼承接口,並可多繼承接口,但類只能單根繼承。
上述語言描述可能很多人都不能夠很好的理解,以下做簡單的說明:
抽象類可以理解爲:一個事物具有的屬性和方法人類具有的屬性,性別,年齡,出生年月日,方法,喫喝拉撒睡等等。是描述一個事物固有的屬性和動作。
接口可以理解爲:一個事物可以實現的功能人類可以學習,可以逛街,可以打遊戲等等。

疑問:那麼抽象類和接口都可以實現喫飯逛街打豆豆這種行爲,他們之間有何區別呢?
答:抽象類是被單根繼承的,如果要以子類實例化該抽象類,那麼它是單根繼承的,也就是說,我不能既是人類又是非人類。但是接口可以被多繼承,我可以喫飯逛街打豆豆,但我不影響我是人類。所以在實現某些功能的時候,如果要實現某事物的本質,那麼需要用到抽象類,如果實現事物的方法,則使用接口。

對於轉載文章所提到的10點,我用代碼和一些文字加以說明,來幫助自己理解。

1.抽象類和接口都不能直接實例化,如果要實例化,抽象類變量必須指向實現所有抽象方法的子類對象,接口變量必須指向實現所有接口方法的類對象。

abstract class Human(var name:String)
{	
	fun eat()
	fun drink()  //錯誤,提示必須要在喫喝方法前加入abstract或者實現上述方法
}

如果定義一個抽象類human,具有喫喝的方法,如果該類是抽象的,那麼它的方法也應當是抽象的,也就是說,我知道這是個人,只能知道他可以喫喝,但是不能知道他怎麼喫喝。如果要知道怎麼喫喝,就得具體到這個人是誰。如果要具體的想知道是誰就要去找到這個人是誰,就需要子類對象去繼承該抽象類。
所以

abstract class Human(var name:String)
{	
	abstract fun eat()
	abstract fun drink()
}

此時 子類創建的實例就能知道這個人喫飯和喝水的具體行爲是怎樣的

class Man:Human(name=String())
{
	override fun eat()
	{
		println("細嚼慢嚥")
	}
	override fun drink()
	{
		println("大口喝水")
	}
}

如果我們定義一個接口:

interface eatdinner
{
	fun eatdinner(name:String)
}

這個接口用來實現eatdinner這個行爲,但是如果我們不在調用這個接口的類中調用該變量,那麼這個接口是無法實例化的。所以需要

class Man:Human(name=String()),eatdinner    //要注意的是繼承抽象類需要類名(),方法只需要名字
{
	override fun eat()
	{
		println("細嚼慢嚥")
	}
	override fun drink()
	{
		println("大口喝水")
	}
	override fun eatdinner(name:String)
	{
		println("影響均衡的喫")
	}
}

2、抽象類要被子類繼承,接口要被類實現。

還是用上面的代碼舉例子,抽象類定義好了屬性和方法,抽象類Human由子類定義並實例化後,人具有這個屬性和方法。但是接口在被類中調用後,是實現了某個行爲。就好像是,定義出一個人,是人都可以喫喝。但是如果要去進行釣魚玩遊戲這個行爲,要某個特殊的人做某個具體動作纔行。

3、接口只能做方法申明,抽象類中可以做方法申明,也可以做方法實現

abstract class Human(var name:String)
{	
	fun eat()   //eat就是方法實現
	{
		println("用嘴喫")  
	}
	abstract fun drink()  //drink是方法申明
}

以上例子中,如果用到了方法實現,那麼子類繼承後是無法進行override的,就好像我定義了喫必須用嘴,但我不能重寫一個用耳朵喫飯。

interface eatdinner
{
	fun eatdinner()
	{
		println("自由實現")
	}
}

接口的內部方法可以定義也可以實現,但作用只是用來申明,你可以進行修改也可以不修改。但是抽象類內的方法一旦實現,是不可以進行修改的。

class Man:Human(name=String()),eatdinner    //要注意的是繼承抽象類需要類名(),方法只需要名字
{
	override fun drink()  //所以在這裏就不需要重寫 eat也不能重寫eat
	{
		println("大口喝水")
	}
	override fun eatdinner(name:String)
	{
		println("營養均衡的喫")
	}
}
fun main(args: Array<String>) {
    var man1=Man()
    man1.eat()//結果爲用嘴喫
    man1.drink()//結果爲大口喝水
    man1.eatdinner("11")//結果爲營養均衡的喫
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章