`

Trail: Learning the Java Language_Lesson: Interfaces and Inheritance2

 
阅读更多

Java中类可以从其他类中派生出来(be derived from),也就是继承机制

 

除了Object,每个类都有一个也只有一个直接父类,不指定就是默认Object的子类

子类将继承父类的所有成员,除了不让继承的

构造并不是类的成员,因此不能继承,但子类构造中可以用super(..)调用父类构造

 

内部类是可以访问外部类的private字段的,所以如果内部类被子类继承了的话,父类的private字段也被间接访问

 

 

MountainBike myBike = (MountainBike)obj;

这个显式转换实际上是在运行时才能检测出错误,编译时总是假设正确

 

如果提前加个

 

if (obj instanceof MountainBike) {

能让运行时不要报错

 

 

 

一个对象可以有很多类型,是通过接口来体现

如果声明一个变量为接口类型,那么赋值的可以是某个实现类的对象,他们的的确确是同一类型

 

类与接口的一个区别就是类中可以有字段,而接口只能有常量

如果类之间允许多重继承,都继承了同名的成员后将会引起混乱

类只能继承一个类,而可以实现多个接口

 

子类可以覆盖父类方法,这个意义在于,子类只需寻找类似的父类就行了,然后改改就能用,对父类的要求并不严格

 

覆盖的方法修饰符可以更宽

试图把父类的实例方法覆盖成static或反过来,会编译报错

实例方法跟父类实例方法同名,叫覆盖

static方法跟父类static方法同名,叫隐藏(hiding)

子类字段跟父类字段同名,也会隐藏 //不推荐这样

到底调用的是哪个方法要看声明的类名(类型)

 

接口中的abstract方法和default方法都是非static的,也就是实例方法,他们可以被子接口覆盖

 

接口的static方法是不会被继承的

super也可以用来调用实现的接口里的default方法,是最直接的上层

 

一个英文,polymorphism(多态)

 

 

 

如果父类和多个接口中有同样签名的方法?子类如何区分他们呢?这里有几个规则:

1.实例方法优先于接口的default方法

public class Horse {
    public String identifyMyself() {
        return "I am a horse.";
    }
}
public interface Flyer {
    default public String identifyMyself() {
        return "I am able to fly.";
    }
}
public interface Mythical {
    default public String identifyMyself() {
        return "I am a mythical creature.";
    }
}
public class Pegasus extends Horse implements Flyer, Mythical {
    public static void main(String... args) {
        Pegasus myApp = new Pegasus();
        System.out.println(myApp.identifyMyself());
    }
}

会显示I am a horse.是继承来的实例方法

 

2.已经被覆盖过的方法会被忽略

public interface Animal {
    default public String identifyMyself() {
        return "I am an animal.";
    }
}
public interface EggLayer extends Animal {
    default public String identifyMyself() {
        return "I am able to lay eggs.";
    }
}
public interface FireBreather extends Animal { }
public class Dragon implements EggLayer, FireBreather {
    public static void main (String... args) {
        Dragon myApp = new Dragon();
        System.out.println(myApp.identifyMyself());
    }
}

会显示I am able to lay eggs.是新方法

 

3.子类继承来的方法,可以用来会实现接口的方法

public interface Mammal {
    String identifyMyself();
}
public class Horse {
    public String identifyMyself() {
        return "I am a horse.";
    }
}
public class Mustang extends Horse implements Mammal {
    public static void main(String... args) {
        Mustang myApp = new Mustang();
        System.out.println(myApp.identifyMyself());
    }
}

将显示I am a horse

 

4.无关的多个default方法重名,或跟某个abstract方法重名,会编译报错

 

 

Object的方法:

 

如果一个类或某个父类,实现了Cloneable接口,就可以调用.clone()方法,生成一个拷贝的对象

默认的clone()实现只是复制了一个地址,所指向的依然是同一个对象,所以通常是需要覆盖的

 

而默认的equals()也只是比较两个对象是否==,所以通常是需要覆盖的

 

public boolean equals(Object obj) {
        if (obj instanceof Book)
            return ISBN.equals((Book)obj.getISBN()); 
        else
            return false;
    }//一个覆盖的例子,要手动比较内部成员

 

 

如果覆盖equals(),也必须覆盖hashCode(),默认返回对象内存地址的hex值

 

finalize()默认什么都不做,要覆盖成一些收尾动作,当然不要指望那会执行

 

getClass()方法是不能覆盖的,它返回一个java.lang.Class类的对象,可以得到很多信息

 

toString()通常是需要覆盖的

 

构造方法里所调用的方法通常要定义为final,不让继承的子类修改,保证构造的确定性

一个类定义为final,是不能继承的

 

 

一个类定义为abstract,就是抽象类,可能有abstract方法,也可能没有

抽象类不能实例化,可以被继承

抽象方法没有方法体,包含抽象方法的类必须声明为abstract

抽象类当然可以有静态字段和静态方法

 

抽象类的子类也要实现父类的接口中的方法

 

抽象类使用情形:

1.想在多个有关联的类间共享一些东西

2.通过父类中声明,想让多个子类都拥有很多共同的字段和方法,或者非public的成员

3.想定义非static或非final的字段,可以声明某个方法改变他们

接口的使用情形:

1.想让多个无关联的类共享一些东西

2.想声明某个方法,却不关心怎么实现

3.想多重继承

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics