第八章 接口与抽象类
抽象类
当多个类中出现相同的功能,但是功能主体不同,这时可以进行向上抽取,但是只抽取功能定义,而不抽取功能主体。
比如,猫类可以创建实例,但是不知道猫科动物具体长什么样子,这时就可以将猫科动物类定义为抽象的。
使用abstract关键字将类标记为抽象:
abstract class Feline{
}
抽象类代表没有人能够创建出该类的实例。不过你还是可以使用抽象类来声明为引用类型给多态使用,却不用担心哪个创建该类型的对象,编译器会确保这件事。
abstract class Feline{
}
public class Cat extends Feline{
public void go(){
Feline f;
f = new Cat();
f = new Feline(); //这句是不能通过编译的,因为抽象类无法创建实例
}
}
抽象类无法创建实例,仅仅用于被继承。
抽象的方法
除了类之外,你也可以将方法标记为abstract的。抽象的类代表此类必须要被extends过,抽象的方法代表此方法一定要被覆盖过。
抽象的方法没有实体!因为你已经知道编写出抽象方法的程序代码没有意义,所以不会含有方法。
public abstract void eat();
//抽象方法没有方法体!直接以分号结束
如果你声名出一个抽象的方法,就必须将类也标记为抽象的。你不能在非抽象类中拥有抽象方法。就算只有一个抽象方法,此类也必须标记为抽象的。
如果想继承抽象类,你必须实现所有的抽象方法。实现抽象方法和覆盖方法是一样的。
抽象的方法没有内容,它只是为了标记出多态而存在。这表示在继承树结构下的第一个具体类必须要实现出所有的抽象方法。
然而你还是可以通过抽象机制将实现的负担转给下层。例如说将Animal与Feline都标记为abstract,则Feline就无需实现出Animal的抽象方法。但具体的类,例如说Cat,就得实现出Animal和Feline的抽象方法。
记住抽象类可以带有抽象和非抽象的方法,因此Feline也可以实现Animal的抽象方法,让Cat不必实现这部分。如果Feline没有对Animal的抽象类表示出任何意见,就表示Cat得自己实现出Animal的抽象方法。
Object类
在java中所有的类都是从Object这个类继承出来的,也就是说,Object是所有类的最终父类。
Object中的一些方法:
equals(Object o) //判断两个对象是否相同
Dog d = new Dog();
Cat c = new Cat();
d.equals(c);
getClass()//告诉你此对象是在哪里被初始化的
Cat c = new Cat();
System.out.println(c.getClass()); //打印结果为"class Cat"
hashCode() //列出此对象的哈希代码,你可以把它想象成是一个唯一的ID
Cat c = new Cat();
System.out.println(c.hashCode());
//打印结果是一串哈希代码
toString() //列出类的名称和一个我们并不关心的数字
Cat c = new Cat();
System.out.println(c.toString());
我们可以覆盖Object的方法,最少可以覆盖一部分,因为有些被标记为final,这代表你不能覆盖掉它们。而且强烈建议你用自己写的类去覆盖掉hashCode()、equals()以及toString()。
接口
已知我们已经有了Feline(猫科动物类)和继承了它的Cat(猫类),如果想给猫类增加一个Pet(宠物)属性呢?
直接定义在猫科动物类上并不是一个明智的选择,因为可能老虎类也会继承猫科动物类。
直接定义在猫类里也不太行,因为如果狗类、鼠类也需要Pet属性的话也要分别在狗类和鼠类中定义,很是麻烦。
这种情况我们可以使用
接口,此处讨论的不是GUI接口,也不是“沟通管道”或“存取途径”的接口,我们说的是Java中的interface关键字。
接口解决问题的方法很简单:把全部的方法设为抽象的!如此一来,子类就得要实现此方法,因此Java虚拟机在执行期间就不会搞不清楚要用哪一个继承版本。
Java的接口就好像是100%的纯抽象类,所有接口的方法都是抽象的,所以任何Pet的类都必须要实现这些方法。
接口的定义使用interface关键字:
public interface Pet{
......
}
接口的实现使用implements关键字:
public class Cat extends Feline implements Pet{
.....
}
接口可以被类多实现,对Java不支持多继承的转换形式,java支持多实现。
class Cat extends Feline implements Pet,Saveable,paintable{
.....
}
可以多实现的原因:因为接口中的方法都是抽象的,没有主体。
接口之间可以继承,而且可以多继承(还是因为接口中的方法没有主体,因为都是抽象方法)。
接口用于功能扩展,基本功能定义于类中,扩展功能定义于接口中。