java 繼承 多態(tài)
繼承與多態(tài)是面向?qū)ο蟮恼Z言的兩個重要的特點,深入的認識對運用好這門編程語言非常重要。
今天的內(nèi)容包括兩部分,概念整理和代碼分析。
現(xiàn)附上一段今天寫的代碼,因為對這部分不滿意,之后會填坑重寫。
import java.util.ArrayList;
class Man{
private String name;
private Boolean sex;
private long num;
Man(String name,Boolean sex,long num){
this.name = name;
this.sex = sex;
this.num = num;
}
String getstuname(){return name;}
Boolean getSex(){return sex;};
long getNum(){return num;};
}
/**
* 目標是構(gòu)建一個Manlist類,該類是一個數(shù)組類,通過繼承ArrayList使其成為一個動態(tài)數(shù)組,能夠非常便捷的完成增刪查改的功能
*/
class Manlist extends ArrayList{
protected ArrayList<Man> list;
Manlist(int n){
list = new ArrayList<Man>(n);
}
Manlist(int n,Man[] list1){
list = new ArrayList<Man>(n);
for(int i = 0;i<list1.length;i++)
list.add(list1[i]);
}
void addMember(Man m){
add(m);
}
//對get函數(shù)進行重載,滿足其搜索姓名的要求
Man get(String name){
int flag = 0;
int k = 0;
for(int i=0;i<list.size();i++){
Boolean identify = list.get(i).getstuname().equals(name);
if(identify){
flag = 1;
k = i;
break;
}
}
if(flag == 1)
return list.get(k);
else
return null;
}
Man modifyNum(long No){
int flag = 0;
int k = 0;
for(int i=0;i<list.size();i++){
if(list.get(i).getNum() == No){
flag = 1;
k = i;
break;
}
}
if(flag == 1)
return list.get(k);
else
return null;
}
void deleteMember(String name){
int i;
for(i = 0;i<list.size();i++){
String stuname = list.get(i).getstuname();
if(stuname.equals(name))
break;
}
list.remove(i);
}
void addMember(Man m,int n){
list.add(n,m);
/**
* 第一次運行報錯Index: 8, Size: 0說明動態(tài)數(shù)組arraylist在此前都沒有被調(diào)用
*/
}
void printGroup(){
for(int i = 0;i<list.size();i++){
System.out.println("Name: "+ list.get(i).getstuname()+"\tsex: "+ list.get(i).getSex()+ "\tNum: "+list.get(i).getNum());
}
}
}
繼承的概念
類之間的繼承關(guān)系是面向?qū)ο蟮脑O(shè)計語言的基本特征。
同類事物具有共同性,在同類事物中,每個事物又具有其特殊性。
通過抽象原則舍去對象的特殊性,抽取其共同性,則得到一個適用于一批對象的類,這就是一般類,而具有特殊性的類別稱為特殊類。
通過繼承原則,一般類具有一般類和特殊類共同的屬性和操作,這些在一般類中顯式的定義出來,在特殊類中不必重復(fù)定義。
特殊類的對象則擁有一般類的全部或部分(private除外)屬性和方法,即特殊類對一般類的繼承。
定義子類
java子類對父類的繼承使用extends語句。每個類只能與有一個父類。如果需要使用多個父類的方法,可以通過接口調(diào)用。
class cl extends cl2{
....
}
隱藏屬性
子類默認具有父類privat以外的數(shù)據(jù)成員,但是可以通過在子類申明同名的數(shù)據(jù)成員,將父類的數(shù)據(jù)成員隱藏起來。數(shù)據(jù)成員(屬性)的隱藏意味著父類的數(shù)據(jù)成員依然在,可以通過super
進行訪問。
//SubclassHideDemo.java
class A1{
int a1;
A1(){
a1 = 5;
}
}
class A2 extends A1{
int a1 = 10;
int show1(){return a1;}
int show2(){return super.a1;};
}
public class SubclassHideDemo{
public static void main(String args[]){
A2 ob = new A2();
System.out.println(ob.show1() + "\t" + ob.show2());
}
}
結(jié)果:
10 5
覆蓋方法
子類默認具有父類的非私有方法,可以直接調(diào)用。同時,子類可以構(gòu)造和父類數(shù)據(jù)類型,方法名,形參完全相同,而方法體不同的方法對父類的方法進行覆蓋。覆蓋顧名思義會將父類方法從內(nèi)存抹去,父類方法在子類對象中不再存在,但是子類方法中可以通過super
調(diào)用父類被覆蓋的方法。
//SubclassCoverDemo.java
package com;
class A1{
int a1 = 5;
int b1 = 10;
void print1(){
System.out.println(a1);
}
void print2(){
System.out.println(b1);
}
}
class A2 extends A1{
int a2 = 6;
int b2 = 11;
void print1(){
System.out.println(a2);
}
void print3(){
super.print2();
}
}
public class SubclassCoverDemo{
public static void main(String args[]){
A2 ob = new A2();
ob.print1(); //父類方法被覆蓋
ob.print2(); //使用父類方法
ob.print3(); //子類方法中通過super調(diào)用了父類被覆蓋的方法
}
}
結(jié)果:
6
10
10
super和this的用法
在上一節(jié)中我們兩次使用了super
這個修飾在子類中使用父類的成員和方法,這里對this和super做一個歸納。
- this
this指向當前的對象自身,使用this標識當前對象的成員和方法,可以提高程序的清晰性,減少重名導(dǎo)致的錯誤。
- 用來訪問當前對象的數(shù)據(jù)成員
- 用來訪問當前對象的成員方法
- 當有重載的構(gòu)造方法時,用來引用同類的其他構(gòu)造方法
- super
super指向當前對象的直接父類,當父類的成員和方法被隱藏和覆蓋,而需要引用他們時,可以通過super實現(xiàn)。
- 訪問直接父類被隱藏的數(shù)據(jù)成員
- 調(diào)用直接父類被覆蓋的成員方法
- 調(diào)用直接父類的構(gòu)造方法。
多態(tài)的概念
通過方法的重名現(xiàn)象提高代碼的抽象性和簡潔性。多態(tài)包括兩個層次,同一類下同一方法名的不同形參的使用方式——重載,和父子類下同一方法名的相同形參的使用方式——覆蓋(見上一節(jié))。
重載方法
重載方法是在同一類里對相同方法的不用使用形式,重載要求方法的數(shù)據(jù)類型和方法名完全相同但是形參不相同,形參的不同表現(xiàn)在參數(shù)的個數(shù),數(shù)據(jù)類型和順序。
//Overload.java
package com;
class F{
int i = 0;
int j = 0;
int k = 0;
F(int i){
this.i = i;
}
F(int i,int j){
this(i); //通過this調(diào)用本類的構(gòu)造方法
this.j = j;
}
F(int i,int j,int k){
this(i,j);
this.k = k;
}
void Fprint(){
System.out.println("i = " + i+ " j = " + j + " k = " + k);
}
}
public class Overload{
public static void main(String args[]){
F f1 = new F(5);
F f2 = new F(5,6);
F f3 = new F(5,6,7);
f1.Fprint();
f2.Fprint();
f3.Fprint();
}
}
結(jié)果:
i = 5 j = 0 k = 0
i = 5 j = 6 k = 0
i = 5 j = 6 k = 7