初學(xué)Java語言, 代碼中的extends和implements讓我感到很迷惑,現(xiàn)在終于弄明白它們之間的區(qū)別和用法了。
-
- public inerface Runner
- {
- int ID = 1;
- void run ();
- }
-
- interface Animal extends Runner
- {
- void breathe ();
- }
-
- class Fish implements Animal
- {
- public void run ()
- {
- System.out.println("fish is swimming");
- }
- public void breather()
- {
- System.out.println("fish is bubbing");
- }
- }
-
- abstract LandAnimal implements Animal
- {
-
- public void breather ()
- {
- System.out.println("LandAnimal is breathing");
- }
- }
-
- class Student extends Person implements Runner
- {
- ......
- public void run ()
- {
- System.out.println("the student is running");
- }
- ......
- }
-
-
- interface Flyer
- {
- void fly ();
- }
-
-
- class Bird implements Runner , Flyer
- {
- public void run ()
- {
- System.out.println("the bird is running");
- }
- public void fly ()
- {
- System.out.println("the bird is flying");
- }
- }
-
-
- class TestFish
- {
- public static void main (String args[])
- {
- Fish f = new Fish();
- int j = 0;
- j = Runner.ID;
- j = f.ID;
- }
- }
接口實(shí)現(xiàn)的注意點(diǎn):
a)實(shí)現(xiàn)一個(gè)接口就是要實(shí)現(xiàn)該接口的所有的方法(抽象類除外)。
b)接口中的方法都是抽象的。
c)多個(gè)無關(guān)的類可以實(shí)現(xiàn)同一個(gè)接口,一個(gè)類可以實(shí)現(xiàn)多個(gè)無關(guān)的接口。
extends與implements的區(qū)別:
extends
是繼承父類,只要那個(gè)類不是聲明為final或者那個(gè)類定義為abstract的就能繼承,JAVA中不支持多重繼承,但是可以用接口來實(shí)現(xiàn),這樣就用到了implements,繼承只能繼承一個(gè)類,但implements可以實(shí)現(xiàn)多個(gè)接口,用逗號分開就行了。
比如:
class A extends B implements C,D,E {} (class 子類名 extends 父類名 implenments 接口名)
父類與子類繼承關(guān)系上的不同:
A a = new B(); 結(jié)果a是一個(gè)A類的實(shí)例,只能訪問A中的方法,那么又和A a = new A();有什么區(qū)別呢?
***********************************************************************************************
class B extends A
繼承過后通常會定義一些父類沒有的成員或者方法。
A a = new B();
這樣是可以的,上傳。
a是一個(gè)父類對象的實(shí)例,因而不能訪問子類定義的新成員或方法。
***********************************************************************************************
假如這樣定義:
class A
{
int i;
void f(){}
}
class B extends A
{
int j;
void f(){} //重寫
void g(){}
}
然后:
B b = new B();
b就是子類對象的實(shí)例,不僅能夠訪問自己的屬性和方法,也能夠訪問父類的屬性和方法。諸如b.i,b.j,b.f(),b.g()都是合法的。此時(shí)b.f()是訪問的B中的f()
A a = new B();
a雖然是用的B的構(gòu)造函數(shù),但經(jīng)過upcast,成為父類對象的實(shí)例,不能訪問子類的屬性和方法。a.i,a.f()是合法的,而a.j,a.g()非法。此時(shí)訪問a.f()是訪問B中的f()
***********************************************************************************************
A a = new B(); 這條語句,實(shí)際上有三個(gè)過程:
(1) A a;
將a聲明為父類對象,只是一個(gè)引用,未分配空間
(2) B temp = new B();
通過B類的構(gòu)造函數(shù)建立了一個(gè)B類對象的實(shí)例,也就是初始化
(3) a = (A)temp;
將子類對象temp轉(zhuǎn)換未父類對象并賦給a,這就是上傳(upcast),是安全的。
經(jīng)過以上3個(gè)過程,a就徹底成為了一個(gè)A類的實(shí)例。
子類往往比父類有更多的屬性和方法,上傳只是舍棄,是安全的;而下傳(downcast)有時(shí)會增加,通常是不安全的。
***********************************************************************************************
a.f()對應(yīng)的應(yīng)該是B類的方法f()
調(diào)用構(gòu)造函數(shù)建立實(shí)例過后,對應(yīng)方法的入口已經(jīng)確定了。
如此以來,a雖被上傳為A類,但其中重寫的方法f()仍然是B的方法f()。也就是說,每個(gè)對象知道自己應(yīng)該調(diào)用哪個(gè)方法。
A a1 = new B();
A a2 = new C();
a1,a2兩個(gè)雖然都是A類對象,但各自的f()不同。這正是多態(tài)性的體現(xiàn)。
***********************************************************************************************