JavaRush /Java Blog /Random-TW /物件導向原則

物件導向原則

在 Random-TW 群組發布
你好!你有沒有想過為什麼 Java 是這樣設計的?從某種意義上說,您基於它們創建類別 - 物件、類別具有方法等。但是為什麼語言的結構使得程式由類別和物件組成,而不是由其他東西組成呢?為什麼「對象」的概念被發明並放在最前線?所有語言都是這樣運作的嗎?如果不是,它為 Java 帶來了什麼好處?正如您所看到的,有很多問題:)讓我們在今天的講座中嘗試回答每個問題。

物件導向程式設計原則:

  1. 遺產
  2. 抽象
  3. 封裝
  4. 多態性

什麼是物件導向程式設計(OOP)

當然,Java 由物件和類別組成是有原因的。這不是其創造者的心血來潮,甚至不是他們的發明。還有許多其他基於物件的語言。第一種此類語言稱為 Simula,它於 20 世紀 60 年代在挪威發明。除此之外,Simula 還引入了「類別」和「方法」的概念。 物件導向程式設計原理 - 2
Kristen Nygaard 和 Ole Johan Dahl - Simula 的創作者
從程式設計標準來看,Simula 似乎是一門古老的語言,但它們與 Java 的「家族」聯繫是肉眼可見的。最有可能的是,您可以輕鬆閱讀上面寫的程式碼並一般性地解釋它的作用:)
Begin
  Class Rectangle (Width, Height); Real Width, Height;

   Begin
      Real Area, Perimeter;

      Procedure Update;
      Begin
        Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
        Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
      End of Update;

      Update;
      OutText("Rectangle created: "); OutFix(Width,2,6);
      OutFix(Height,2,6); OutImage;
   End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;

  Begin
      OutText("ColouredRectangle created, color = "); OutText(Color);
      OutImage;
        End of ColouredRectangle;


         Ref(Rectangle) Cr;
   Cr :- New ColouredRectangle(10, 20, "Green");
End;
程式碼範例取自文章Simula - 50 年的 OOP。正如你所看到的,Java和它的祖先並沒有太大的不同:)這是因為Simula的出現標誌著一個新概念的誕生——物件導向程式設計。維基百科給出了以下 OOP 的定義:物件導向程式設計(OOP)是一種基於將程式表示為物件集合的程式設計方法,每個物件都是特定類別的實例,並且這些類別形成繼承層次結構。在我看來,這是非常成功的。您最近開始學習 Java,但其中幾乎沒有您不熟悉的單字:) 如今,OOP 是最常見的程式設計方法。除了 Java 之外,OOP 原理也用在許多您可能聽過的流行語言中。它們是 C++(電腦遊戲開發人員積極使用)、Objective-C 和 Swift(為 Apple 設備編寫程式)、Python(機器學習領域需求最大)、PHP(最受歡迎的 Web 開發語言之一)、 JavaScript(簡單地說他們不做的事情)和許多其他。實際上,OOP 的這些「原則」是什麼?讓我們更詳細地告訴你。

物件導向原則

這是基礎知識。4 個主要特徵共同構成了物件導向程式設計範式。理解它們是成為成功程式設計師的關鍵。 物件導向程式設計原理 - 3

原則1.繼承

好消息是您已經熟悉 OOP 的一些原則!:) 我們已經在講座中遇到過幾次繼承,我們有時間使用它。 繼承是一種允許您基於現有(父)類別描述新類別的機制。在這種情況下,新類別借用了父類別的屬性和功能。為什麼繼承是必要的以及它能帶來什麼好處?首先,程式碼重用。父類別中描述的字段和方法可以在後代類別中使用。如果所有類型的汽車都有10個公共欄位和5個相同的方法,則只需將它們放在父類別中即可Auto。您可以在後代類別中使用它們,沒有任何問題。堅實的優勢:定量(更少的程式碼)和定性(類別變得更簡單)。同時,繼承機制非常靈活,您可以在後代中單獨添加缺少的功能(特定於特定類別的某些欄位或行為)。一般來說,就像在日常生活中一樣:我們在某些​​方面與我們的父母相似,但在某些方面又與他們不同:)

原則 2. 抽象

這是一個非常簡單的原則。抽象意味著突顯物件的主要、最重要的特徵,反之亦然──丟棄次要的、無關緊要的特徵。讓我們不要重新發明輪子,記住一個關於類別的舊講座中的例子。假設我們正在建立一個公司員工的文件櫃。為了創建員工對象,我們編寫了一個類別Employee。哪些特徵對於公司文件中的描述很重要?全名、出生日期、社會安全號碼、納稅識別號碼。但在這種類型的卡片中,我們不太可能需要他的身高、眼睛和頭髮顏色。公司不需要有關員工的這些資訊。因此,對於該類,Employee我們將設定變數String nameint ageint socialInsuranceNumberint taxNumber,我們將放棄對我們來說不必要的訊息,例如眼睛顏色,並將其抽象化。但如果我們為一家代理商創建照片模特兒目錄,情況就會發生巨大變化。為了描述一個時裝模特,身高、眼睛顏色和頭髮顏色對我們來說非常重要,但不需要 TIN 號碼。因此,在類別中Model我們創建變數String height, String hair, String eyes

原則 3:封裝

我們已經遇到過。Java 中的封裝意味著限制對資料的存取和更改資料的能力。正如你所看到的,它是基於“膠囊”這個詞。在這個「膠囊」中,我們隱藏了一些我們不希望任何人更改的重要數據。生活中的一個簡單例子。您有名字和姓氏。你認識的每個人都認識他們。但他們無權更改您的名字和姓氏。有人可能會說,這個過程被「封裝」在護照辦公室:你只能在那裡更改你的名字和姓氏,而且只有你自己可以這樣做。其他「使用者」對您的名字和姓氏具有唯讀存取權:) 另一個例子是您公寓中的錢。把它們放在房間中央顯眼的地方並不是一個好主意。任何「用戶」(來到您家的人)都可以更改您的錢數,即 接他們。最好將它們封裝在保險箱中。只有您才能訪問,並且只能使用特殊代碼。您已經使用過的封裝的明顯範例是存取修飾符(privatepublic)和 getter-setter。如果age類別欄位Cat沒有被封裝,任何人都可以寫:
Cat.age = -1000;
封裝機制允許我們使用agesetter 方法來保護字段,在該方法中我們可以檢查年齡不能為負數。

原理 4. 多態性

多態性是指將多種類型視為相同類型的能力。在這種情況下,物件的行為將根據它們所屬的類型而有所不同。聽起來有點複雜?現在我們就來弄清楚吧。讓我們舉一個最簡單的例子──動物。讓我們建立一個Animal具有單一方法 -voice()及其兩個子方法 -Cat和的類別Dog
public class Animal {

   public void voice() {

       System.out.println("Voice!");
   }
}

public class Dog extends Animal {


   @Override
   public void voice() {
       System.out.println("Bow-wow!");
   }
}

public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}
現在讓我們嘗試建立一個連結Animal並為其分配一個物件Dog
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.voice();
   }
}
您認為會呼叫哪個方法?Animal.voice()或者Dog.voice()?類別方法將被呼叫Dog:Woof-woof!我們創建了一個引用Animal,但該物件的行為類似於Dog. 如果有必要,他可以表現得像貓、馬或其他動物。主要是將通用類型的參考分配Animal給特定後代類別的物件。這是合乎邏輯的,因為所有的狗都是動物。這就是我們所說的「物件的行為會根據它們的類型而有所不同」。如果我們要建立一個物件Cat-
public static void main(String[] args) {

   Animal cat = new Cat();
   cat.voice();
}
該方法voice()將輸出“喵!” 「能夠像處理相同類型一樣處理多種類型」是什麼意思?這也很容易。讓我們想像一下,我們正在為動物創建一個美髮沙龍。我們的美髮沙龍必須能夠切割所有動物,因此我們將創建一個shear()帶有參數的方法(“切割”)Animal——我們要切割的動物。
public class AnimalBarbershop {

   public void shear(Animal animal) {

       System.out.println("The haircut is ready!");
   }
}
現在我們可以將shear物件Cat和物件傳遞給方法Dog
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.shear(cat);
   barbershop.shear(dog);
}
這是一個明顯的例子:該類別AnimalBarbershop使用類型,就好像它們是相同的類型Cat一樣。Dog同時,他們的行為Cat也不同Dog:他們以不同的方式使用自己的聲音。

OOP出現的原因

為什麼會出現這種新的程式設計概念—OOP?程式設計師擁有有效的工具:例如過程語言。是什麼促使他們發明了一些全新的東西?首先,他們面臨的任務的複雜性。如果60 年前,程式設計師的任務看起來像是“計算這樣那樣的數學方程式”,那麼現在聽起來可能像是“根據用戶在遊戲時刻A、B、C、D 中做出的決定,為STALKER遊戲實現7 個不同的結局” 、E、F 以及這些解決方案的組合。” 正如您所看到的,過去幾十年來,任務顯然變得更加複雜。這意味著資料類型變得更加複雜。這是OOP出現的另一個原因。帶有方程式的範例可以使用普通基元輕鬆求解;這裡不需要任何物件。但是,如果不使用您發明的某些類,甚至很難用遊戲結局來描述問題。但同時,用類別和物件來描述它也很容易:我們顯然需要 Game 類別、Stalker 類別、Ending 類別、Player's Decision 類別、Game Moment 類別等等。也就是說,即使沒有開始解決問題,我們也可以輕鬆地在腦海中想像出解決方案的「草圖」。問題日益複雜,迫使程式設計師將問題分成幾個部分。但在過程程式設計中這並不那麼容易。通常,程式是一棵由一堆分支組成的“樹”,具有所有可能的操作選項。根據某些條件,程式沿著一個分支或另一個分支執行。對於小型程式來說,這個選項很方便,但將大型任務分成幾個部分卻非常困難。這種需要成為OOP出現的另一個原因。這個概念使程式設計師能夠將程式劃分為一堆類別的“模組”,每個模組都完成自己的部分工作。所有相互作用的對象構成了我們程序的工作。另外,我們寫的程式碼可以在程式的其他地方重複使用,這也節省了大量的時間。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION