參考鏈接: Java中的繼承
繼承:?
繼承就是保持已有類的特性而構造新類的過程。繼承后,子類能夠利用父類中定義的變量和方法,就像它們屬于子類本身一樣。?
單繼承:在類層次中,子類只繼承一個父類的數據結構和方法,一個類只有一個父類?
多繼承:在類層次中,子類繼承了多個父類的數據結構和方法,一個類允許有多個繼承?
(java支持多層繼承)?
//父類
public class file{
? ? public long size;? ? ?//文件大小
? ? public String name;? ? //文件名
? ? public void info()? ? //顯示文件信息
? ? {
? ? ? ? System.out.println(name + " " + size);
? ? }
}
//子類
public class videofile extends file()
{
? ? //父類的public成員自動繼承
? ? //private不能被繼承,子類無權訪問? ??
? ? //只需要添加子類的特性
? ? public int duration //時長? ??
? ? public void play()
? ? {
? ? ? ?System.out.println("播放" + this.name);
? ? }
? ? public void stop()
? ? {
? ? ? ? System.out.println("停止" + this.name);
? ? }
}?
成員變量隱藏:是指在子類中定義了一個與直接超類的某個成員變量同名的成員變量,從而使超類中的那個成員變量不能直接被子類繼承。?
當成員變量隱藏時,在超類類題代碼中用簡單變量命名訪問的一定是超類中的成員變量,而在子類類體代碼中用簡單變量名訪問的則一定是在子類中的成員變量?
可以用下列各式訪問超類中被隱藏的成員變量?
super.<變量名>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 在子類類體里,訪問直接超類中被隱藏的成員變量?
((<超類名>)<子類實例引用>).變量名? ? 訪問指定超類中被隱藏的成員變量?
<超類名>.<變量名>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?訪問指定超類中被隱藏的類變量?
public class number {
? ? int x;
? ? static int y; //類變量
? ? void set(int a)
? ? {
? ? ? ? x = a;
? ? ? ? y = a;
? ? }
? ? void print()
? ? {
? ? ? ? System.out.println("x" + "\t" + x);
? ? }
}
?
public class newnumber extends number {
? ? int x;
? ? static int y;
? ? void newset(int a)
? ? {
? ? ? ? x = a;
? ? ? ? y = a;
? ? }
? ? void newprint()
? ? {
? ? ? ? System.out.println("x" + "\t" + x);? ? ?//x = 100
? ? ? ? System.out.println("y" + "\t" + y);? ? ?//y = 100
? ? ? ? System.out.println("x" + "\t" + super.x);? ? ?//x = 10
? ? ? ? //在子類類體里,訪問直接超類中被隱藏的成員變量
? ? ? ? System.out.println("y" + "\t" + super.y);? ? ?//y = 10
? ? }
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? ? ? newnumber n = new newnumber();
? ? ? ? n.set(10);
? ? ? ? n.print();?
? ? ? ? n.newset(100);
? ? ? ? n.newprint();
? ? ? ? System.out.println("y" + "\t" + number.y);? ? ?//y = 10
? ? ? ? System.out.println("x" + "\t" + ((number)n).x);? ? ?//x= 10
? ? }
}?
若子類和父類里都有相同的名字定義的方法,但是實現不一致。覆蓋的方法是按照子類中重定義的方法進行調用,而繼承的方法直接調用父類的方法?
覆蓋 (重寫)(Override):?
1、方法名稱要一樣?
2、返回值數據類型要一樣?
3、所使用的參數列表要一樣,參數列表包括參數個數及每個參數的數據類型,不包括參數的變量名?
4、訪問修飾符只能越來越開放,不能越來越封閉?
public class file {
? ? public long size;
? ? public String name;
? ? public void info()
? ? {
? ? ? ? System.out.println(name +? "\t" + size);
? ? }
}
?
public class vediofile extends file{
? ? public int duration;
? ? public void play()
? ? {
? ? ? ? System.out.println("播放" + this.name);
? ? }
? ? public void stop()
? ? {
? ? ? ? System.out.println("停止" + this.name);
? ? }
? ? ?//Override 覆蓋
? ? public void info() {
? ? ? ? ?System.out.println("name : " + name + "? size : " + size + " time : " + time);
? ? ? ? }
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? ? ? vediofile v = new vediofile();
? ? v.size = 20000;
? ? v.name = "abc.mp4";
? ? v.duration = 70;
? ? v.info();?
? ? //name : abc.mp4? size : 20000? time : 70
? ? }
}?
泛化:?
抽取調整代碼到父類的過程,稱為泛化?
Eclipse自動添加覆蓋功能:?
點擊source,選擇Override/Implement Methods?
?
選擇要覆蓋的方法?
?
創建完成?
?
子類可以選擇完全重寫或者在父類方法中補充?
public void info() {
? ? ? ? // TODO Auto-generated method stub
? ? ? ? super.info();? ? //調用父類的實現
? ? ? ? System.out.println("time : " + duration);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? //name : abc.mp4? size : 20000? time : 70
? ? }?
構造方法的繼承:?
創建子類對象時,父類的構造方法會被自動調用?
public class parent {
? ? public parent()
? ? {
? ? ? ? System.out.println("父類構造...");
? ? }
}
?
public class child extends parent {
? ? public child()
? ? {
? ? ? ? System.out.println("子類構造...");
? ? }
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? ? ? child c = new child();????????????
? ? }
}?
?
若父類有很多個構造方法,可以在子類里顯示指定用哪個構造方法?
public class parent {
? ? private int a;
? ? public parent()? ? //默認構造
? ? {
? ? ? ? System.out.println("父類構造...");
? ? }
? ? public parent(int a)? ? ?//帶參構造
? ? {
? ? ? ? this.a = a;
? ? ? ? System.out.println("帶參父類構造...");
? ? }
}
?
public class child extends parent {
? ? public child()
? ? {
? ? ? ? super(23);? ? //調用帶參構造
? ? ? ? System.out.println("子類構造...");
? ? }
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? child c = new child();????
? ? }
}?
單根繼承:Java語言里,一個類只能繼承一個父類?
如果一個類沒有指定父類,則它的默認父類就是Object?
toString() 方法返回此對象本身(它已經是一個字符串)?
public class Student {
? ? public String id;
? ? public String name;
? ? public boolean sex;
? ? @Override
? ? public String toString() {
? ? ? ? String s = " 學號 : " + id + " 姓名 : " + name;
? ? ? ? if(sex)
? ? ? ? {
? ? ? ? ? ? s = s + "(男)";
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? s = s + "(女)";
? ? ? ? }
? ? ? ? return s;
? ? }?
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? ? ? Student s = new Student();
? ? ? ? s.id = "20003";
? ? ? ? s.name = "lisi";
? ? ? ? System.out.println(s.toString());? ? // 學號 20003 姓名 lisi(女)
? ? }
}?
多態?
1、使用父類類型的引用只想子類的對象?
2、該引用只能調用父類中定義的方法和變量?
3、如果子類中重寫(覆蓋)了父類中的一個方法,那么在調用這個方法的時候,將會調用子類中的這個方法?
4、變量不能被重寫(覆蓋),重寫只針對方法,如果在子類中重寫了父類的變量,編譯時會報錯?
子類轉成父類是可以的(隱式轉換)?
當調用一個方法的時候,不是看引用類型,而是看對象的實際類型。?
轉化原則?
子類對象可以當作父類對象使用?
父類對象不能當作子類對象使用?
如果父類引用實際只想的是子類對象,那么該父類引用可以通過強制轉化成子類對象使用?
public class file {
? ? public long size;
? ? public String name;
? ? public void info()
? ? {
? ? ? ? System.out.println("name : " + name + "? size : " + size);
? ? }
}
?
public class vediofile extends file{
? ? public int duration;
? ? public void play()
? ? {
? ? ? ? System.out.println("播放" + this.name);
? ? }
? ? public void stop()
? ? {
? ? ? ? System.out.println("停止" + this.name);
? ? }
? ? @Override
? ? public void info() {
? ? ? ? // TODO Auto-generated method stub
? ? ? ? super.info();
? ? ? ? System.out.println("time : " + duration);
? ? }????
}
?
public class HelloWorld {
? ? public static void main(String[] args) {
? ? ? ? vediofile v = new vediofile();
? ? ? ? v.size = 20000;
? ? ? ? v.name = "abc.mp4";
? ? ? ? v.duration = 70;
? ? ? ? file f = v;
? ? ? ? f.info();? ? ?//調用的子類的info
? ? }
}?
覆蓋是動態綁定?
重載是靜態綁定?
用instanceof操作符測試一個對象是否是一個類的實例?
instanceof返回值是true或false?
對象名 instanceof 類名 -> true or false?
class SchoolMember
{??
? ? public void introduce()
? ? {
? ? ? ? System.out.println("a schoolmember");
? ? }
?}
?
class Student extends SchoolMember
{?
? ? public void study()
? ? {
? ? ? ? System.out.println("study");
? ? }? ?????
}
class Teacher extends SchoolMember
{
? ? public void teach()
? ? {
? ? ? ? System.out.println("teach");
? ? }
}
class Test
{
? ? static void use(SchoolMember obj)
? ? {
? ? ? ? obj.introduce();
? ? ? ? //判斷實例化的對象是Student還是Teacher
? ? ? ? if(obj instanceof Student)? ? ?
? ? ? ? {
? ? ? ? ? ? Student s = (Student)obj;
? ? ? ? ? ? s.study();
? ? ? ? }
? ? ? ? if(obj instanceof Teacher)
? ? ? ? {
? ? ? ? ? ? Teacher t = (Teacher)obj;
? ? ? ? ? ? t.teach();
? ? ? ? }
? ? }
? ? public static void main(String[] args)
? ? {
? ? ? ? Student s1 = new Student();
? ? ? ? //Teacher t1 = new Teacher();
? ? ? ? use(s1);
? ? ? ? //use(t1);
? ? }
}
?
eg:
a schoolmember
study
?
方法看右側,屬性看左側?
先訪問父類的構造方法再訪問子類的構造方法?
eg1:?
class A
? ? {? ? ?String? s="class A";? ? }
? ? class B extends A
? ? {? ? ?String? s="class B";? ? }
? ? public class TypeConvert
? ? {
? ? ? ? public static void main(String args[])
? ? ? ? {
? ? ? ? ? ? B b1,b2=new B();
? ? ? ? ? ? A a1,a2;
? ? ? ? ? ? a1=(A)b2;
? ? ? ? ? ? a2=b2;
? ? ? ? ? ? System.out.println(a1.s);? ? //class A
? ? ? ? ? ? System.out.println(a2.s);? ? //class A
? ? ? ? ? ? b1=(B)a1;
? ? ? ? ? ? System.out.println(b1.s);? ? //class B
? ? ? ? ? ? System.out.println(b2.s);? ? //class B
?
? ? ? ? }
? ? }
?
?
eg2 :?
class A
? ? {? ? ?String s="class A";??
? ? ? ? ? void show()? ? {? ? ? ?System.out.println(s);}
? }
? ? class B extends A
? ? {? ? ?String s="class B";? ??
? ? ? ? void show()? ? ? {? ?System.out.println(s);}
}
? ? public class TypeConvert
? ? {? ? public static void main(String args[])? ? ? ? {
? ? ? ? ? ? B b1;
? ? ? ? ? ? B b2=new B();
? ? ? ? ? ? A a1,a2;
? ? ? ? ? ? a1=(A)b2;
? ? ? ? ? ? a2=b2;
? ? ? ? ? ? System.out.println(a1.s);? ? //class A
? ? ? ? ? ? a1.show();? ? //class B
? ? ? ? ? ? System.out.println(a2.s);? ? //class A
? ? ? ? ? ? a2.show();? ? //class B
? ? ? ? ? ? b1=(B)a1;
? ? ? ? ? ? System.out.println(b1.s);? ? //class B
? ? ? ? ? ? b1.show();? ? //class B
? ? ? ? ? ? System.out.println(b2.s);? ? //class B
? ? ? ? ? ? b2.show();? ? //class B
? ? ? ? }
? ? }?
eg3:?
class A
{
? ? public A()
? ? {
? ? ? ? System.out.println(“The default constructor of A is invoked”);
}
}
class B extends A
{
? ? public B()
? ? {
? ? }
}
public class C
{
? ? public static void main(String[] args)
? ? {
? ? ? ? B b = new B();
? ? }
}
輸出 The default constructor of A is invoked