接口与多态
抽象类是无法初始化的类(就是不能“new”出来了)
Animal anim=new Animal();
没
有animal对象呀,所以不能初始化,就有了抽象类
编译器不会让你初始化抽象类
抽象类代表没有人能够创建出该类的实例,你还是可以使用抽象类来声明为引用类型给多态使用,却不用担心哪个创建该类型的对象,编译器会确保这件事。
设计抽象类,用关键字abstract
abstract public class Canine extends Animal
{
public void roam(){ }
}
public class MakeCanine{
public void go(){
Canine c;
c=new Dog();//这两个是可以的,因为你乐意复制子类对象给父类的引用,即使父类是抽象的
c=new Canine();//这个类以及被标记为abstract,所以过不了编译这一关
c.roam();
}
}
抽象类除了被继承过以外,是没有用途,没有值,没有目的的(除了抽象的class可以有static的成员之外)
抽象与具体
不是抽象的类被称为具体类
抽象的方法
抽象的类代表此类必须要被extend过,抽象的方法代表此方法一定要被覆盖过。
抽象的方法没有实体
public abstract void eat();//没有方法体,直接以分号结束
如果你声明出一个抽象的方法,就必须将类也标记为抽象的,你不能在非抽象类中拥有抽象方法。就算只有一个抽象的方法,此类也必须标记为抽象的
抽象类可以带有抽象和非抽象的方法
抽象的好处就是多态,达成的目标是要使父类作为方法的参数,返回类型或数组的类型。
抽象方法的意义是就算无法实现出方法的内容,但还是可以定义出一组子型共同的协议。
实现抽象的方法就如同覆盖过方法一样
抽象的方法没有内容,它只是为了标记出多态而存在,这表示在继承树结构下的第一个具体类必须要实现出所有的抽象方法,然而你还是可以通过抽象机制将实现的负担转给下层
eg:将Animal与Canine都标记为abstract,则Canine就无需实现出Animal的抽象方法,但下面具体的类就得实现了。
当我们说“你必须实现所有的抽象的方法”,表示说你必须写出内容,你必须以相同的方法鉴明(名称和参数)和相容的返回类型创建出非抽象的方法。
注意:
private Animal[ ] animal=new Animal[5];
//这不是在创建Animal对象,只是保存Animal的数组对象;
Object类
在java中的所有类都是从Object这个类继承出来的;它是所有类的源头;所有类的父类;
equals(Object o)
Dog a=new Dog();
Cat c=new Cat();
if(a.equals(c){
System.out.println("true");
}else{
System.out.println("false");
}
//让你知道两个对象是相等的
hashCode()
Cat c=new Cat();
System.out.println(c.hashCode());
//列出此对象的哈希代码,可以想象成唯一的
getClass()
Cat c=new.Cat();
System.out.println(c.getClass());
//告诉你此对象是从哪里被初始化的
toString()
Cat c=new Cat();
System.out.println(c.toString());
//列出类的名称和一个我们不关心的数字
任何从ArrayList取出来的东西都会被当做Object类型的引用而不管它原来是什么;(就是出来后都为Object)
错误案例
public void go(){
Dog aDog=new Dog();
Dog sameDog=getObject(aDog);//只能赋值给Object类型的变量
}
public Object getObject(Object o){
return o;//返回一个引用,但是类型已经转变成Object了
}
只要
Object sameDog=getObject(aDog);
就行了
编译器是根据引用类型来判断有哪些method可以调用,而不是根据Object确实的类型,就算知道对象有这个功能,编译器还是会把它当作一般的Object来看待。编译器只管引用的类型,而不是对象的类型。
然后就可以转换为原来类型
Object o=al.get(index);
Dog d=(Dog) o;//将类型转换为Dog
d.roam();
但如果不能确定它是Dog,你可以使用instanceof这个运算符来检查,若是类型转换错了,你会在执行期间遇到ClassCastException异常并且终止;
if(o instanceof Dog){
Dog d=(Dog) o;
}
java注重引用变量的类型
接口
要在dog,cat类里增加pet的方法而不影响其他以animal为父类的子类
public interface Pet{
public abstract void beFriendly();//接口的方法一定是抽象的,以分号结束;
public abstract void play();
}
public class Dog extends Canine implements Pet{//implements关键字后面跟着接口的名称;
public void beFriendly(){...}必须在这里实现出Pet的方法,这是合约的规定
public void play(){...}
public void roam(){...}//一般的覆盖方法
public void eat(){...}
}
且类可以实现多个接口
eg:
public class Dog extends Animal implements Pet,Savable,paintable{...}
extend只能有一个,implement可以有好多个;
1.如果新的类无法对其他的类通过IS-A测试时,就设计不能继承的类;
2.只有在需要某种类的特殊化版本时,以覆盖或增加新的方法来继承现有的类;
3.当你需要某种定义一群子类的模板,又不想让程序员初始化此模版时,设计出抽象的类给它们用;
4.如果想要定义出类可以扮演的角色,使用接口
调用父类的方法
使用super这个关键字
abstract class Report{
void runReport(){//父类的方法,带有子类可以运行的部分;
//设置报告
}
void printReport(){
//输出
}
}
class BuzzwordsReport extends Report{
void runReport()
super.runReport();//调用父类的方法
buzzwordCompliance();
printfReport();
}
void buzzwordCompliance(){...}
}