1. 程式人生 > >封裝,繼承,多態,接口

封裝,繼承,多態,接口

一個 寫法 方式 interface 員工 私有 屬於 dev emp

封裝

封裝的概述和好處:

  1. 是面向對象三大特征之一
  2. 是面向對象編程語言對客觀世界的模擬,客觀世界裏成員變量都是隱藏在對象內部的,外界無法直接操作和修改。

封裝原則:

  1. 將不需要對外提供的內容都隱藏起來。

  2. 把屬性隱藏,提供公共方法對其訪問。

  3. 成員變量private,提供對應的getXxx()/setXxx()方法

好處:

  1. 通過方法來控制成員變量的操作,提高了代碼的安全性

  2. 把代碼用方法進行封裝,提高了代碼的復用性

public class Student {
	String name;
	//int age;
	Private int age;
	
	Public void setAge(inta) {
		if(a<0 || a>200) {
			System.out.println("你給的年齡有誤");
		}else {
			age = a;
		}
	}
	
	Public int getAge() {
		returnage;
	}
	
	Public void show() {
		System.out.println("姓名是:"+name+",年齡是:"+age);
	}
}
public class DemoStudent {
	public static void main(String[] args) {
		//創建學生對象
		Student s = new Student();
		s.show(); ?????????????
		
		s.name = "柳巖";
		//s.age = 18;
		//s.age = -18;
		//s.setAge(-18);
		s.setAge(28);
		s.show();
	}
}

繼承:

在程序中,如果想聲明一個類繼承另一個類,需要使用extends關鍵字。

  格式:

class 子類 extends 父類 {

}

父類內容,子類可以使用

子類特有內容,可以寫在子類中.

class Employee {
	String name; // 定義name屬性
	// 定義員工的工作方法
	publicvoid work() {
		System.out.println("盡心盡力地工作");
	}
}

/*
 * 定義講師類Teacher繼承員工類Employee
 */
classTeacherextends Employee {
	// 定義一個打印name的方法
	publicvoidprintName() {
		System.out.println("name=" + name);
	}
}

/*
 * 定義測試類
 */
publicclass Example01 {
	publicstaticvoid main(String[] args) {
		Teachert = newTeacher (); // 創建一個講師類對象
		t.name = "小明"; // 為該員工類的name屬性進行賦值
		t.printName(); // 調用該員工的printName()方法
		t.work(); // 調用Developer類繼承來的work()方法
	}
}

  

在上述代碼中,Teacher類通過extends關鍵字繼承了Employee類,這樣Teacher類便是Employee類的子類。從運行結果不難看出,子類雖然沒有定義name屬性和work()方法,但是卻能訪問這兩個成員。這就說明,子類在繼承父類的時候,會自動擁有父類的成員。

小結:

繼承是面向對象的核心特性,是面向對象的學習重點。

繼承是代碼復用的重要方式,是類與類之間的一種關系。

從類與類之間的設計關系來看,子類必須屬於父類的一種時,才會繼承。

父類抽取出了共性的內容,子類可以在父類基礎上擴展新的屬性與行為。

子類擁有父類的所有屬性與方法,無需重新定義。並且可以直接使用非私有的父類成員。

Fu類中的成員變量是非私有的,子類中可以直接訪問,若Fu類中的成員變量私有了,子類是不能直接訪問的。

當子父類中出現了同名成員變量時,在子類中若要訪問父類中的成員變量,必須使用關鍵字super來完成。super用來表示當前對象中包含的父類對象空間的引用。

在子類中,訪問父類中的成員變量格式:

super.父類中的成員變量

class Fu
{
	//Fu中的成員變量。
	intnum = 5;
}
classZi extends Fu
{
	//Zi中的成員變量
	intnum = 6;
	void show()
	{
		//子父類中出現了同名的成員變量時
		//在子類中需要訪問父類中非私有成員變量時,需要使用super關鍵字
		//訪問父類中的num
		System.out.println("Fu num="+super.num);
		//訪問子類中的num2
		System.out.println("Zi num2="+this.num);
	}
}
class Demo5 
{
	public static void main(String[] args) 
	{
		Zi z = new Zi(); //創建子類對象
		z.show(); //調用子類中的show方法
	}
}

  

繼承-子父類中成員方法特點

當在程序中通過對象調用方法時,會先在子類中查找有沒有對應的方法,若子類中存在就會執行子類中的方法,若子類中不存在就會執行父類中相應的方法。

class Fu{
	publicvoid show(){
		System.out.println("Fu類中的show方法執行");
	}
}
classZi extends Fu{
	public void show2(){
		System.out.println("Zi類中的show2方法執行");
	}
}
public  class Test{
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show(); //子類中沒有show方法,但是可以找到父類方法去執行
		z.show2();
	}
}

  

繼承特點

Java支持單繼承

Java支持多層繼承

父類定義了繼承樹中共性內容,子類定義了該類個性內容。

在結合多態後,能使用父類時盡量使用父類,提高程序擴展性。

繼承的註意點:

1.java中不支持類的多繼承

class Fu{
}
class Zi extends Fu{
}

class Zi2 extends Zi, Object{// 錯誤寫法
}

2. java中支持多層繼承

class Grand{}

class Fu extends Grand{}

class Zi extends Fu{}

  

缺點:
1. 不支持多繼承(但是保留了多繼承的機制,通過接口體現)
2. 增強類與類之間的耦合性(通過接口的方式可以解決)

附加知識:

this:
含義:
誰調用了this所在的方法, this就代表誰.
//1. 使用在方法中, 解決了成員變量和局部變量重名的問題

public void setName(String name) {
this.name = name;
}

 //2. 可以調用構造方法, 構造方法之間的相互調用(了解即可)

public Student(){
}

public Student(String name){
this();
}

 //3. 調用普通的成員方法, 學了繼承之後,可以區分子父類的方法

public void show(){
}
public void print(){
this.show();
}

  

匿名對象:
有名字的對象
Student stu = new Student();

匿名對象:
new Student();

使用場景:
1. 用來臨時調用一個方法
2. 可以作為方法參數
3. 可以作為方法的返回值

多態

多態概述:

多態是繼封裝、繼承之後,面向對象的第三大特性。

現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。

Java中多態的代碼體現在一個子類對象(實現類對象)既可以給這個子類(實現類對象)引用變量賦值,又可以給這個子類(實現類對象)的父類(接口)變量賦值。

Student類可以為Person類的子類。那麽一個Student對象既可以賦值給一個Student類型的引用,也可以賦值給一個Person類型的引用。

^^^^最終多態體現為父類引用變量可以指向子類對象。!!!!!!!!!!!!!!!!!!!

多態的前提是必須有子父類關系或者類實現接口關系,否則無法完成多態。

在使用多態後的父類引用變量調用方法時,會調用子類重寫後的方法。

具體格式如下:

父類引用指向子類對象就是多態的定義格式。同一個父類的方法會被不同的子類重寫為各自的具體實現。在調用方法時,調用的為各個子類重寫後的方法。

父類類型 變量名 = new 子類類型();

變量名.方法名();

此時,雖然該變量指向的是子類對象,但表現為一個父類的形態,可以調用一切父類的方法,子類特有的方法將不能調用。

我們一般在以下場景當中使用多態:

1 成員變量賦值、局部變量賦值

2 方法傳參(最常用最能體現出多態優點的應用)

3 返回返回值

多態的存在意義

當變量名指向不同的子類對象時,由於每個子類重寫父類方法的內容不同,所以會調用不同的方法。

所以多態的存在意義(優點)為:

配合繼承與方法重寫提高了代碼的復用性與擴展性,如果沒有方法重寫,則多態同樣沒有意義。

向上向下類型轉換

多態本身是子類類型向父類類型向上轉型的過程。

多態的轉型分為向上轉型與向下轉型兩種:

1 向上轉型:當有子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。

使用格式:

父類類型 變量名 = new 子類類型();

如:Person p = new Student();

2 向下轉型:一個已經向上轉型的子類對象可以使用強制類型轉換的格式,將父類引用轉為子類引用,這個過程是向下轉型。如果是直接創建父類對象,是無法向下轉型的!

使用格式:

子類類型 變量名 = (子類類型) 父類類型的變量;

:Student stu = (Student) p; //變量p 實際上指向Student對象

接口:

接口是功能的集合,同樣可看做是一種數據類型,是比抽象類更為抽象的”類”。

接口只描述所應該具備的方法,並沒有具體實現,具體的實現由接口的實現類(相當於接口的子類)來完成這樣將功能的定義與實現分離,優化了程序設計。

請記住:一切事物均有功能,即一切事物均有接口

接口的定義:

與定義類的class不同,接口定義時需要使用interface關鍵字。

定義接口所在的仍為.java文件,雖然聲明時使用的為interface關鍵字的編譯後仍然會產生.class文件。這點可以讓我們將接口看做是一種只包含了功能聲明的特殊類。

定義格式:

public interface 接口名 {

抽象方法1;

抽象方法2;

抽象方法3;

}

使用interface代替了原來的class,其他步驟與定義類相同:

1 接口中的方法均為公共訪問的抽象方法

2 接口中無法定義普通的成員變量

類實現接口

類與接口的關系為實現關系,即類實現接口實現的動作類似繼承,只是關鍵字不同,實現使用implements。

其他類(實現類)實現接口後,就相當於聲明:”我應該具備這個接口中的功能”。實現類仍然需要重寫方法以實現具體的功能。

格式:

class implements 接口 {

重寫接口中方法

}

在類實現接口後,該類就會將接口中的抽象方法繼承過來,此時該類需要重寫該接口的所有抽象方法,完成具體的邏輯。

1 接口中定義功能,當需要具有該功能時,可以讓類實現該接口,只聲明了應該具備該方法,是功能的聲明。

2 在具體實現類中重寫方法,實現功能,是方法的具體實現。

於是,通過以上兩個動作將功能的聲明與實現便分開了。(此時請重新思考:類是現實事物的描述,接口是功能的集合。)

接口中成員的特點

1、接口中可以定義變量,但是變量必須有固定的修飾符修飾,public static final 所以接口中的變量也稱之為常量,其值不能改變。後面我們會講解staticfinal關鍵字

2、接口中可以定義方法,方法也有固定的修飾符,public abstract

3、接口不可以創建對象。

4、子類必須覆蓋掉接口中所有的抽象方法後,子類才可以實例化。否則子類是一個抽象類。

interface Demo { ///定義一個名稱為Demo的接口。
	public static final int NUM = 3;// NUM的值不能改變
	public abstract void show1();
	public abstract void show2();
}

//定義子類去覆蓋接口中的方法。類與接口之間的關系是 實現。通過 關鍵字 implements
class DemoImpl implements Demo { //子類實現Demo接口。
	//重寫接口中的方法。
	public void show1(){}
	public void show2(){}
}

  

接口特點

1 接口可以繼承接口

如同類繼承類後便擁有了父類的成員,可以使用父類的非私有成員。A接口繼承B接口後,A接口便擁有了AB兩個接口中所有的抽象方法。

2 Java支持一個類同時實現多個接口,或一個接口同時繼承多個接口。

3 類可以在繼承一個類的同時,實現多個接口。

4 接口與父類的功能可以重復,均代表要具備某種功能,並不沖突

接口和抽象類的區別

相同點:

1 都位於繼承的頂端,用於被其他類實現或繼承;

2 都不能直接實例化對象;

3都包含抽象方法,其子類都必須覆寫這些抽象方法;

區別:

1 抽象類為部分方法提供實現,避免子類重復實現這些方法,提高代碼重用性;接口只能包含抽象方法;

2 一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個接口;(接口彌補了Java的單繼承)

二者的選用:

1 優先選用接口,盡量少用抽象類;

2 需要定義子類的行為,又要為子類提供共性功能時才選用抽象類;

封裝,繼承,多態,接口