第八章 接口与多态
暑期实习刚好处在开发工作岗上,因为之前没有太接触过JAVA,所以开启边学边用模式。其实已经开始学习一个星期了,但是直到今天才开始打算写博客。作为一个程序菜鸡,记录一下学习记录吧。
1. 抽象与具体
上一章主要内容主要是JAVA中如何继承,这一章首先说明我们一般声明引用变量的时候将其与具体对象相连接,例如:
Wolf awolf = new Wolf();
Animal Ahippo = new Hippo();
但有时候有一些类例如是较高阶的类是没有具体的定义的,例如它们向上父类动物,我们就不能这样定义:
Animal anim = new Animal();
因为没有人知道这个“anim”到底是个什么样的动物,它会让程序变得奇怪。
为了防止抽象的类被定义,我们会在类的声明前用到关键词“abstract”,它可以让一些没有必要或只用于被继承的类无法被初始化,用法如下:
abstract public class Animal(){
public void roam( ) { }
public void makenoise() { }
...
}
除了抽象的class可以有static的成员之外,第十章描述
2. 抽象的方法
方法也可以被抽象,但是抽象的方法表示此方法一定要被覆盖。
抽象的方法没有实体!
public abstract void eat();
如果你声明除一个抽象的方法,就必须将类也标记为抽象的。你不能在非抽象的类中拥有抽象的方法。就算只有一个抽象的方法,此类也应标记为抽象的。
抽象的方法没有内容,它只是为了标记出多态而存在的
总而言之,抽象的方法总需要被实现,你可以在最后具体的对象中将其实现,也可以在次级类中将其实现。
3. Object
Objcet是终极对象,所有类都继承于Object, 例如boolean, equals()等都是object中自带的方法,这些方法会被继承给所有的类,这就是为什么有些方法我们能直接用。
object不是JAVA中正常的类,所以我们不能用是否抽象类来评论它。其中大部分方法是不可修改的,因为被标记有final,这表示你不能覆盖它们。
你可以把某个引用变量声明为object,但它经常会造成一些问题,例如:
ArrayList <object> myDogArrayList = new ArrayList <object> ();
Dog aDog = new Dog();
myDogArrayList.add(aDog);
//上面都可以正常运行,你可以把Dog类的aDOG放进object类的arraylist
//但是下面这句编译器会报错
Dog d = myDogArrayList.get(0); //报错!!!
原因是你不管把什么类放入声明为object的表中,取出时会自动变成object类,就是说Dog被取出的时候已经不是狗了(?),变成了虚幻的object,而这种object是不可以被赋值给Dog d的。
放大了说就是object能容纳任何类型的类,但是被提取时都会同化为object。
假设你定义了一个名为snowboard的类,这个堆上其实包涵snowboard和其中的objcet。“多态”意味着“很多形式”
,你可以把snowboard当作snowboard或者object。
其实有种方法也可以把object变回原来的类
object o = al.get(index);
Dog d = (Dog) o; //把狗从object变回来了···
d.roam(); //这时候引用对象d表示的狗可以闲逛了···
4. 多重继承与接口
多重继承 指的是某些情况下我们需要两个上级父类用于继承给子类某些特性。例如,狗,猫,老虎,狮子,犀牛都是动物父类下的子类,但是如果我想向其中添加一个宠物的功能,最好的方法就是再设置一个宠物父类,并将其与狗,猫相连。这样能保证老虎,狮子,犀牛不会有宠物特性,对于新加进来的仓鼠等具备宠物特性的动物,我们直接将其再继承宠物父类就好。
但是多重继承有时候会引发致命方块问题,如两个父类中都有相同名称的方法时,子类并不知道该继承其中的哪一个方法。这时候就需要接口。
接口 用来解决多重继承的问题,同时又不会产生致命方块这种问题。JAVA的接口就如100%的纯抽象类
,所有接口的方法都是抽象的,所以任何它的子类都要去实现这些方法。
//接口的的定义及实现
public interface Pet{...} //使用interface来代替class
public class Dog extends Canine implements Pet {...}.
//运用implements来继承接口
// example
public interface Pet{
public abstract void beFriendly(); //必须为抽象方法,以分号结尾
public abstract void play();
}
public class Dog extends Canine implements Pet {
public void beFriendly() {...} // 必须实现pet的方法,这是合约
public void play() {...}
public void roam() {...}. // 一般的覆盖方法
public void eat() {...}
//子类可继承多个接口
public class Dog extends Animal implements Pet, Saveable, paintable {...}
5. 调用父类方法
子类中如果运用super
可以在覆盖后还能调用父类的方法
abstract class Report {
void runReport() {...}. //父类方法,子类也可以运用
void printReport() {...}
}
class BuzzwordsReport extends Report {
void runReport() {
super.runReport(); //调用父类方法
buzzwordCompliance();
printReport();
}
void buzzwordCompliance() {...}
}
6. 书中总结
- 如果不想让某个类被初始化,就以abstract这个关键词将它标记为抽象的
- 抽象的类可以带有抽象和非抽象的方法
- 如果类带有抽象的方法,则此类必定标示为抽象的
- 抽象的方法没有内容,它的声明时以分号结束
- 抽象的方法必须在具体的类中运行
- Java所有的类都是Object直接或间接的子类
- 方法可以声明Object的参数或返回类型
- 不管实际上所引用的对象是什么类型,只有在引用变量的类型就是带有某方法的类型时才能调用该方法
- object引用变量在没有类型转换的情况下不能赋值给其他的类型,若堆上的对象类型与所要转换的类型不兼容,则此转换会在执行期产生异常
类型转换例子 Dog d = (Dog) x.getObject(aDog) - 从ArrayList取出的对象只能被OBject引用,不然就要用类型转换来改变
- Java不允许多重继承,因为那样就有致命方块的问题
- 接口就如100%纯天然抽象类
- 以interface这个关键词取代class来声明接口
- 实现接口时要使用implement这个关键词
- class可以实现多个接口
- 实现某接口的类必须实现它所有的方法,因为这些方法都是public与abstract的
- 要从子类调用父类的方法可以用super这个关键词来引用
例如: super.RunReport();