- 接口 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")//结果为营养均衡的吃
}