面向對象編程:封裝,繼承,多態

封裝

封裝概述

封裝(Encapsulation)是面向對象方法的重要原則,就是把對象的屬性和操作(或服務)結合爲一個獨立的整體,並儘可能隱藏對象的內部實現細節。

類是Java中最小的一個單位,它體現了一種封裝的思想,封裝了成員變量(屬性)和成員方法(功能)
如何定義一個類

class 類名{
成員變量
成員方法(){
}
}

如何使用類
類是一個很抽象的概念,無法直接使用,若想使用該類,需要先對其進行實例化,即創建該類的對象,對象時該類的具體表現
** 如何創建對象**
使用 new關鍵字就可以創建該類對象
格式

類名 對象名 = new 類名();

比如說現在有一個student

Student   s=new Student()

方法

Java方法是語句的集合,它們在一起執行一個功能
方法的定義

修飾符 返回值類型 方法名(參數類型 參數名){
    ...
    方法體
    ...
    return 返回值;
}
  • 修飾符:是可選的,它定義了方法的訪問類型。
  • 返回返回類型:void是指沒有沒有特定的返回值,但如果改爲其他的例如int ,double那麼就一定要有一個返回值了
  • 方法名:是該方法的名字,由大家自己定義
  • 參數類型:聲明瞭參數的數據類型,例如第一個例子中的int表示參數是int類型
  • 參數名:參數的名字,例如第一個代碼例子中的a和b就是參數的名字
  • 方法體:該方法具體想實現的功能
  • return:結束方法,並返回指定的類型
  • 返回值:方法的結果,由return帶回
    ** 方法的調用**
    Java 支持兩種調用方法的方式,根據方法是否返回值來選擇。當程序調用一個方法時,程序的控制權交給了被調用的方法。當被調用方法的返回語句執行或者到達方法體閉括號時候交還控制權給程序。
    1.當方法返回一個值的時候,方法調用通常被當做一個值
    2.如果方法返回值是void,方法調用一定是一條語句。
    例:
class demo1{
    public static void main(String[] args) {
        test1();
        System.out.println(test2());
    }
    public static void test1() {
        System.out.println("你好世界");
    }
    public static int test2(){
        return 2;
    }
}

通過值傳遞參數
在定義方法時,如果定義了形式參數,那麼在調用時就要提供參數,要按照參數列表所給定的順序傳入

 public static void test(int a,String b){
        System.out.println(b+"-----------"+a);
    }

此方法在調用時就需要傳入兩個參數,第一個是int類型的,第二個是String類型的

test2(5,"name");

** 方法重載**
方法重載是指在一個類中定義多個同名的方法,但要求每個方法具有不同的參數的類型或參數的個數,方法重載與返回值類型,返回值,參數名都沒有關係。
構造方法
語法
方法名和類名相同,沒有返回值類型,連void都沒有。根據方法有無參數,我們將其分爲有參構造方法和無參構造方法,在我們定義的類中都會有一個默認的無參構造
舉例

public Student(){
	System.out.println("這是一個無參構造");
}
public Student(){
	System.out.println("這是一個有參構造");
	this.name=name;
}

注意:在一個類中,如果寫了一個有參構造,那麼就不會有默認的無參構造方法了,如果要用到無參構造方法需要自己寫一個。
作用
用來完成對類的初始化

代碼塊

** 概述**
在Java中,使用{}括起來的代碼被稱爲代碼塊。
局部代碼塊
在方法中出現;限定變量生命週期,及早釋放,提高內存利用率
舉例

public class demo {
    public static void main(String[] args) {
        { 
            int x = 3;
            System.out.println("普通代碼塊內的變量x=" + x);
        }
        int x = 1;
        System.out.println("主方法內的變量x=" + x);
        
    }
} 

構造代碼塊
在類中方法外出現;多個構造方法方法中相同的代碼存放到一起,每次調用構造都執行,並且在構造方法前執行
舉例

class test{
    public test(){
        System.out.println("這是一個無參構造方法");
    }
    public test(int a){
        System.out.println("這是一個有參構造方法,參數是a,a="+a);
    }
}
public class demo {
    public static void main(String[] args) {
        new test();
        new test(5);
    }
}

靜態代碼塊
在類中方法外出現,並加上static修飾;用於給類進行初始化,在加載的時候就執行,並且只執行一次。
舉例

class test{
    public test(){
        System.out.println("這是一個無參構造方法");
    }
    public test(int a){
        System.out.println("這是一個有參構造方法,參數是a,a="+a);
    }
    static {
        System.out.println("test的靜態代碼塊");
    }
}
public class demo {
    public static void main(String[] args) {
        new test();
        new test(5);
    }
}

封裝的好處

1.對象的數據封裝特性徹底消除了傳統結構方法中數據與操作分離所帶來的種種問題,提高了程序的可複用性和可維護性,降低了程序員保持數據與操作內容的負擔。
2.對象的數據封裝特性還可以把對象的私有數據和公共數據分離開,保護了私有數據,減少了可能的模塊間干擾,達到降低程序複雜性、提高可控性的目的

繼承

繼承概述

繼承是面向對象最顯著的一個特性,Java繼承是使用已存在的類的定義作爲基礎建立新類的技術,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。關鍵字:extent
** 繼承的格式**

class 子類名 extent  父類名{
}

** 繼承的注意事項**
1.父類私有成員無法被繼承(private修飾的)
2.構造方法不參與繼承
3.Java中不支持多繼承,但支持多層繼承
4.不要爲了一小部分功能使用繼承,這會增加代碼的耦合性
這與代碼開發規則:高內聚,低耦合 相悖

關鍵字this與super

this 代表本類的一個引用,可以理解爲本類的一個對象,誰調用就代表誰
super 是父類空間的標識,可以理解爲父類的一個對象
this的用法
1.普通的直接引用
這種就不用講了,this相當於是指向當前對象本身
2.形參與成員名字重名,用this來區分:

class Person {
    private int age = 10;
    public Person(){
    System.out.println("初始化年齡:"+age);
}
    public int GetAge(int age){
        this.age = age;
        return this.age;
    }
}
 
public class test1 {
    public static void main(String[] args) {
        Person Harry = new Person();
        System.out.println("Harry's age is: "+Harry.GetAge(12));
    }
}       

輸出爲

初始化年齡:10
Harry's age is:12

3.引用構造函數
放在下面和super一起看
super用法
1.值接引用
指向當前對象的父類,super.XXX表示父類的成員
2.子類中的變量和方法與父類中的重名
例如:

 class people {
    String name;
    public void demo(){
        name="小剛";
    }
}
class student extends people{
    String name="小明";
    public void demo() {
        super.demo();//調用父類方法
        System.out.println(name);
        System.out.println(super.name);
    }

    public static void main(String[] args) {
        student st= new student();
        st.demo();
    }
}

運行結果

小明
小剛

3.引用構造函數
super(參數):調用父類中的某一個構造函數(應該爲構造函數中的第一條語句)。
this(參數):調用本類中另一種形式的構造函數(應該爲構造函數中的第一條語句)。

class Person { 
    public static void prt(String s) { 
       System.out.println(s); 
    } 
   
    Person() { 
       prt("父類·無參數構造方法: "+"A Person."); 
    }//構造方法(1) 
    
    Person(String name) { 
       prt("父類·含一個參數的構造方法: "+"A person's name is " + name); 
    }//構造方法(2) 
} 
    
public class Chinese extends Person { 
    Chinese() { 
       super(); // 調用父類構造方法(1) 
       prt("子類·調用父類”無參數構造方法“: "+"A chinese coder."); 
    } 
    
    Chinese(String name) { 
       super(name);// 調用父類具有相同形參的構造方法(2) 
       prt("子類·調用父類”含一個參數的構造方法“: "+"his name is " + name); 
    } 
    
    Chinese(String name, int age) { 
       this(name);// 調用具有相同形參的構造方法(3) 
       prt("子類:調用子類具有相同形參的構造方法:his age is " + age); 
    } 
    
    public static void main(String[] args) { 
       Chinese cn = new Chinese(); 
       cn = new Chinese("codersai"); 
       cn = new Chinese("codersai", 18); 
    } 
}

繼承的中構造方法
繼承中構造函數的關係
子類中所有的構造方法默認都會訪問父類中空參數的構造方法。這是因爲子類會繼承父類中的數據,可能還會使用父類的數據。所以,子類初始化之前,一定要先完成父類數據的初始化,每一個構造方法的第一條語句默認都是:super(),這一點在上面的super和this的用法中也有提到
** 繼承中構造方法的注意事項**
如果父類沒有無參構造方法,子類初始化怎麼辦?
1. 在父類中添加一個無參的構造方法
2.子類通過super去顯示調用父類其他的帶參的構造方法
3.子類通過this去調用本類的其他構造方法,本類其他構造也必須首先訪問了父類構造
注意事項
super(…)或者this(….)必須出現在第一條語句上,這在上面的super和this的用法中也有提到
** 方法重寫**
當父類和子類的方法申明(方法名,返回值類型,參數列表)一樣時,子類的方法就會覆蓋掉父類的方法,這樣的現象稱之爲方法重寫。當子類需要父類的功能,而功能主體子類有自己特有內容時,可以重寫父類中的方法。這樣,即沿襲了父類的功能,又定義了子類特有的內容。
舉例

class animal{
    int age;
    public void eat(){
        System.out.println("吃東西");        
    }
}
class cat extends animal{
    @Override
    public void eat() {
        System.out.println("貓吃魚");
    }
}
class dog extends animal{
    public void eat() {
        System.out.println("狗吃肉");
    }
}

方法重寫的注意事項
1.父類中私有方法不能被重寫,因爲父類私有方法子類根本就無法繼承
2.:子類重寫父類方法時,訪問權限不能更低最好就一致
(四個權限修飾符 public> (空缺的,什麼都不寫) >protect>private )
3.靜態方法不參與重寫

final關鍵字

** final用法**
由於繼承中有一個方法重寫的現象,而有時候我們不想讓子類去重寫父類的方法.這對這種情況java就給我們提供了一個關鍵字: final
final可以修飾類,成員方法,變量

final class demo {
    final  int a=100;//變量變爲常量
    public final void show(){
    } //該該方法無法被重寫
}//該類無法被繼承

** final修飾特點**
修飾類: 被修飾類不能被繼承
修飾方法: 被修飾的方法不能被重寫
修飾變量: 被修飾的變量不能被重新賦值,因爲這個量其實是一個常量
修飾引用類型:其地址無法被修改

繼承的優點與弊端

優點
1.提高了代碼的複用性
2.提高了代碼的維護性
3.讓類與類之間產生了關係,是多態的前提
弊端
增加了代碼的耦合性,這違背可開發的原則:高內聚,低耦合

多態

多態概述

在面嚮對象語言中,接口的多種不同的實現方式即爲多態,簡單的說,就是允許將子類類型的指針賦值給父類類型的指針。

Cat c=new Cat();
Animal a=new Cat();

多態存在的必要條件

1.繼承
2.方法重寫
3.父類引用指向子類

多態中成員訪問特點

1.成員變量:編譯看左邊,運行看左邊
2.構造方法:創建子類對象的時候,會訪問父類的構造方法,對父類的數據進行初始化。
3.成員方法:編譯看左邊,運行看右邊。
4.靜態方法:編譯看左邊,運行看左邊。
(靜態和類相關,算不上重寫,所以,訪問還是左邊的)

class Super {
	int index = 5;
	public void printVal() {
		System.out.println("Super");
	}
}
class Sub extends Super {
	int index = 2;
	public void printVal(){
		System.out.println("Sub");
	}
}
class Demo {
	public static void main(String[] args) {
		Super sup = new Sub();
		System.out.print(sup.index + ",");//成員變量:編譯看左邊,運行看左邊
		sup.printVal();//成員方法:編譯看左邊,運行看右邊
	}
}

多態的優點以及弊端

優點
1.提高了代碼的維護性(繼承保證)
2.提高了代碼的擴展性(由多態保證)
弊端
不能使用子類特有的功能

向下轉型

把父類的引用強制轉換爲子類的引用。用來解決多態的弊端
舉例

public class MyTest{
    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.num);
        fu.show();
        Zi zi= (Zi) fu;//向下轉型
        System.out.println(zi.num);
        zi.mehtod();
    }

}

class Fu{
    int num=100;
    public void show(){
        System.out.println("fu  show");
    }
}
class Zi extends Fu{
    int num=10;

    @Override
    public void show() {
        System.out.println("zi show");
    }
    public void mehtod(){
        System.out.println("子類特有的方法");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章