- 接口 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")//結果爲營養均衡的喫
}