💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 抽象类定义 [TOC] 我们之前说“人会尿尿,男人是站着尿尿,女人是蹲着尿尿”,在基类人(Person)中定义了尿尿的方法(niaoniao),但其实基类人(Person)不知道怎么定义尿尿的行为,站着也不行,蹲着也不是,应该交给子类男人(Man)、子类女人(Woman)具体去定义尿尿行为。 **在程序世界里面,基类中某个方法,基类不知道具体实现,需要交给子类去具体实现,我们可以把这个方法定义为抽象方法**。那怎么把方法变成抽象方法呢?**去掉方法体,方法上加上abstract关键字即可**,类似这样: ~~~ abstract fun niaoniao():String ~~~ **一个类如果包含了抽象方法,那么这个类需要变成抽象类**。那怎么把类变成抽象类呢?类的前面,加上abstract关键字即可,类似这样: ~~~ abstract open class Person(val name: String) { abstract fun niaoniao(): String } ~~~ ## 抽象类实现 ### 基本实现 我们把“人会尿尿,男人是站着尿尿,女人是蹲着尿尿”这样的例子,通过抽象类和抽象方法实现一下,参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-60e6c16c15d38424.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 针对以上代码只是把niaoniao方法改成了抽象方法,Person类改成了抽象类,其他没有改变。 * [ ] **总结** 在定义抽象类时需要注意,包含抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法,只需使用abstract关键字来修饰即可。另外,抽象类是不可以被实例化的,因为抽象类中有可能包含抽象方法,抽象方法是没有方法体的,不可以被调用。如果想调用抽象类中定义的方法,则需要创建一个子类,在子类中将抽象类中的抽象方法进行实现。 示例 ``` abstract class Animal(){ abstract fun eat() } class Monkey(food: String):Animal(){ var food = food; override fun eat() { println("猴子正在吃$food。") } } fun main(args: Array<String>) { var monkey = Monkey("香蕉") monkey.eat() } ``` 运行结果 ``` 猴子正在吃香蕉。 ``` 从运行结果可以看出,子类实现了父类的抽象方法后,可以正常进行实例化,并通过实例化对象调用实现的方法。 ### **可包含方法实现** 但是**抽象类,可包含方法实现(就是说抽象类可包含非抽象方法)**,类似这样也是可以的: ![](http://upload-images.jianshu.io/upload_images/7368752-1c1e7d687819d924.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 我们对上面代码做相应修改,参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-615659aeb91a8f22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### **不能被实例化** **抽象类不能被实例化,只能作为基类,被其他类所继承**。我们通过代码验证下,参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-63f07b779f4ca683.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### **子类必须实现抽象方法或者变成抽象类** 一个类继承了抽象类,要么实现所有的抽象方法,要么再把自身变成抽象类。**抽象类可以包含非抽象方法**。参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-43081172f7d80103.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 我们看到Man没有实现niaoniao的方法,就需要通过**abstract**关键字继续把类变成抽象类。 ### **抽象方法必须public或者protected(默认就是)** 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。参考截图: ![](http://upload-images.jianshu.io/upload_images/7368752-3bd808d94146ffae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### **可包含属性** **抽象类,还可以包含抽象属性**,也就是通过**abstract**关键字修饰的属性,**如果抽象类中含有抽象属性,子类中必须将抽象属性初始化,除非子类也为抽象类**。参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-138a07ad91c55bab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### **属性不可实例化(初始化)** 虽然,**抽象类可以包含属性,但是只能包含属性的定义,属性不能实例化,Java中的抽象类中的属性,可以初始化,也可以不初始化**,参考截图: ![](http://upload-images.jianshu.io/upload_images/7368752-5f36cbd708aaa231.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)