12-13java面向對象之繼承

繼承

概念:用於擴充已有類的功能。例如:人類作爲一個大的類描述了宏觀的情況,學生又是一個人類中的特例,學生類既具備人類的共性也有自己的個性。
語法:

Class 子類名稱 extends 父類名稱{}
注意:子類被成爲派生類,父類被成爲超類。子類繼承了父類的一些可以使用的操作,同時具備了父類不具備的操作。
//本程序是對繼承的測試
class Person
{
	//封裝屬性
	private String name;
	private int age;
	//方法
	public void setName(String n)
	{
		name=n;
	}
	public void setAge(int n)
	{
		if (n>=0)
		{
			age=n;
		}
	}
	public String getName()	
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String getInfo()
	{
		return "姓名:" + this.name + ",年齡:" + this.age;
	}
}
//子類的繼承
class Student extends Person
{
	private String school;
	public void setSchool(String school)
	{
		this.school = school;
	}
	public String getSchool()
	{
		return this.school;
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.setName("Tyrion");				//此方法進行繼承
		stu.setAge(24);
		stu.setSchool("BUAA");
		System.out.println( stu.getInfo()+",學校:" + stu.getSchool() );
	}
}
上例中,stu繼承了Person類的特性,所有的public方法都可以使用。同時也具備了父類Person不具備的school屬性。

子類在繼承時只能繼承所有非私有操作,父類的所有私有操作是隱式繼承,不能直接訪問。但是一般都可以通過非私有的方法進行操作。

//本程序是對繼承的測試
class Person
{
	private void print()
	{
		System.out.println("hello");
	}
}

//子類的繼承
class Student extends Person
{
	
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.print();
	}
}


由於print()方法只在父類中採用定義是private,所以不能訪問。

限制:一個子類只能有一個父類,但是允許多層繼承。

例如: class A extends B{}   class B extends C{}

現實情況:總是現有父親才能後有子女,所以說父類優先與子類的產生。子類在進行實例化的時候會默認調用父類的構造方法(默認使用無參),之後調用自己的構造方法,這時候相當於子類的構造方法有 super()

//本程序是對繼承的測試
class Person
{
	//父類的構造方法
	public Person()
	{
		System.out.println("!!!!!!這是父類的構造方法");
	}
}

//子類的繼承
class Student extends Person
{
	public Student()
	{
        super();
		System.out.println("!!!!!!這是子類的構造方法");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
	}
}
結果;

如果父類中明確定義了無參構造方法的話,super()可以不寫,但是如果父類的構造方法使用的是有參數,那麼必須寫super(參數),且帶上相應的參數,寫在第一行。——————>相應要求父類的構造方法中,默認寫上無參構造。

//本程序是對繼承的測試
class Person
{
	//父類的構造方法
	public Person(int i)
	{
		System.out.println("!!!!!!這是父類的構造方法");
	}
}

//子類的繼承
class Student extends Person
{
	public Student(int x ,String a)
	{
		super(x);
		System.out.println("!!!!!!這是子類的構造方法");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student(1,"sd");
	}
}

提示:thissuper都要寫在第一行,所以他倆不能同時出現

覆寫

繼承反生了之後,方法和屬性名稱相同,該怎麼辦?

概念:子類和父類的方法名稱完全相同。

//本程序是對繼承的測試
class Person
{
	public void fun()
	{
		System.out.println("Person類中fun");
	}
}

//子類的繼承
class Student extends Person
{
	public void fun()
	{
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.fun();
	}
}
結果:


此時調用使用的是子類的方法,如果子類沒有父類的方法,由於繼承的關係,子類可以調用父類的非私有操作,那麼就調用父類的方法。所以調用的方法是被覆寫了的方法。

如果父子類方法名稱相同,但是參數列表不同,那麼也不是覆寫,對象能夠自動找到滿足要求的方法並調用之。

//本程序是對繼承的測試
class Person
{
	public void fun()
	{
		System.out.println("Person類中fun");
	}
}

//子類的繼承
class Student extends Person
{
	public void fun(int x)
	{
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.fun();
	}
}

根據“就近取用”的原則,stu對象會在student類中找方法,沒有的話,到父類中尋找。

覆寫的限制條件:

1.方法的返回值不同,則不能覆寫,所以覆寫要求返回值類型必須相同。

//本程序是對繼承的測試
class Person
{
	public int fun()
	{
		System.out.println("Person類中fun");
		return 1;
	}
}

//子類的繼承
class Student extends Person
{
	public String fun()
	{
		System.out.println("Student類中fun");
		return "s";
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		//stu.fun();
		System.out.println(stu.fun());
	}
}
錯誤信息:TestInherance.java:14: 錯誤: Student中的fun()無法覆蓋Person中的fun()  

 public String fun()                     ^
  返回類型String與int不兼容

限制2:被覆寫的方法不能擁有比父類更加嚴格的權限。

public> default >private

//本程序是對繼承的測試
class Person
{
	void fun()
	{
		System.out.println("Person類中fun");
	}
}

//子類的繼承
class Student extends Person
{
	private void fun()//必須是比父類更高的權限
	{
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.fun();
	}
}
錯誤信息:

TestInherance.java:13: 錯誤: Student中的fun()無法覆蓋Person中的fun()
        private void fun()//必須是比父類更高的權限                     ^
  正在嘗試分配更低的訪問權限; 以前爲package
TestInherance.java:23: 錯誤: fun()可以在Student中訪問private
                stu.fun();

但是有時候,子類覆寫的父類的方法,但是又想調用父類的方法,怎麼辦?使用super關鍵字指明使用父類,否則默認使用this,就近取用,先在子類中尋找後再父類中尋找。

錯誤版本

//本程序是對繼承的測試
class Person
{
	void fun()
	{
		System.out.println("Person類中fun");
	}
}

//子類的繼承
class Student extends Person
{
	void fun()
	{
		<span style="background-color: rgb(255, 255, 51);">fun();</span>
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.fun();
	}
}
就近取用,遞歸死循環

正確版本

//本程序是對繼承的測試
class Person
{
	void fun()
	{
		System.out.println("Person類中fun");
	}
}

//子類的繼承
class Student extends Person
{
	void fun()
	{
		super.fun();
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.fun();
	}
}
問題來了:如果父類的方法定義爲private,那麼子類使用default權限是不是覆寫呢?
//本程序是對繼承的測試
class Person
{
	private void fun()
	{
		System.out.println("Person類中fun");
	}
	public void print()
	{
		this.fun();
	}
}

//子類的繼承
class Student extends Person
{
	void fun()
	{
		//super.fun();
		System.out.println("Student類中fun");
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();
		stu.print();
	}
}
加入覆寫成功,那麼調用this.fun這個fun肯定就是子類的fun了但是結果


總結:

不管如何操作,只要使用子類的實例化對象,那麼通過子類實例化對象調用的方法都是被覆寫過的方法

屬性的覆寫就沒有必要再說明了,應爲屬性都封裝起來,沒有必要對他們進行直接操作。

總結例題

//本程序是對繼承的測試
class Person
{
	private String name;
	private int age;
	public Person()
	{}
	public Person(String name, int age)
	{
		setName(name);
		setAge(age);
	}
	public void setName(String n)
	{
		name=n;
	}
	public void setAge(int n)
	{
		if (n>=0)
		{
			age=n;
		}
	}
	public String getName()	
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String getInfo()
	{
		return "姓名:" + name +"   " + "年齡:" + age;
	}
}

//子類的繼承
class Student extends Person
{
	private String school;
	public Student()
	{}
	public Student(String name, int age ,String school)
	{
		super(name,age);
		setSchool(school);
	}
	public void setSchool(String school)
	{
		this.school = school;
	}
	public String getSchool()
	{
		return this.school;
	}
	//覆寫了
	public String getInfo()
	{
		return super.getInfo() + ",學校:" + getSchool();
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Student stu = new Student("Tyrion", 24 , "BUAA");
		System.out.println(stu.getInfo());
	}
}

Fianl關鍵字

用於方法,類,屬性

1.使用final定義的類,不能有子類

2.使用final定義的方法,不能被子類覆寫

3.使用final定義的變量,變爲常量,定義的時候必須有內容,不能夠修改。

構造方法私有化(Singleton-單例設計

如果構造方法使用private進行限制,那麼在實例化對象的時候就會出錯,因爲他限制了構造方法只能在內部使用。所以可以編寫另一個方法,該方法使用static關鍵字,不用實例化對象可以返回該類。

//本程序是對繼承的測試
class Singleton
{
	//私有化構造方法
	private Singleton()
	{
	}
	public void print()
	{
		System.out.println("hello world");
	}
	public static Singleton getSingleton()
	{
		return new Singleton();
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Singleton s = null;
		s.getSingleton().print();
	}
}

但是這種方法太過麻煩,要求:

從類的內部產生一個實例化,用get獲取該對象,無論外部有多少對象,只操作了一個對象。

//本程序是對繼承的測試
class Singleton
{
	private static final Singleton instance = new Singleton();
	//私有化構造方法
	private Singleton()
	{
	}
	public void print()
	{
		System.out.println("hello world");
	}
	public static Singleton getInstance()
	{
		return instance;
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Singleton s = null;
		s.getInstance().print();
	}
}

從類的內部產生了一個實例化對象,get獲取該實例化對象,無論外部多少個對象,只操作了這一個對象,所以永遠只有一個對象,加上final

多例設計

在單例中準備一個實例化對象,多例設計要求準備多個實例化對象,要想限制實例化個數,必須要有私有化構造方法。同時在類內部準備多個對象,用static返回該對象。

//本程序是對繼承的測試
class Color
{
	//屬性封裝
	private String cl;
	//產生實例化對象
	private static final Color red = new Color("紅色");
	private static final Color green = new Color("綠色");
	private static final Color blue = new Color("藍色");
	//私有化構造方法
	private Color(String cl)
	{
		this.cl = cl;
	}
	//輸出實例化對象
	public static Color getColor(int x)
	{
		switch (x )
		{
		case 0:
			return red;
		case 1:
			return green;
		case 2:
			return blue;
		default :
			return null;		
		}
	}
	public String print()
	{
		return this.cl;
	}
}
public class TestInherance 
{
	public static void main(String[] args) 
	{
		Color l = null;
		System.out.println(l.getColor(0).print());
		System.out.println(l.getColor(1).print());
		System.out.println(l.getColor(2).print());
	}
}




祝大家健健康康,快快樂樂。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章