CodeGym /Java Blog /Toto sisi /面向對象原則
John Squirrels
等級 41
San Francisco

面向對象原則

在 Toto sisi 群組發布
你好!在今天的課程中,我們將討論面向對象編程的原則。您是否想過為什麼 Java 的設計完全如此?我的意思是,你聲明類並基於類創建對象,類有方法等等。但是為什麼語言的結構使得程序由類和對象組成,而不是其他東西?為什麼要發明“對象”的概念並將其放在首位?所有的語言都是這樣設計的嗎?如果不是,它給 Java 帶來了什麼優勢?如您所見,有很多問題 :) 讓我們在今天的課程中嘗試回答每個問題。

什麼是面向對象編程 (OOP)?

當然,Java 並不是為了好玩而由對象和類組成的。它們不是 Java 的創造者心血來潮,甚至不是他們的發明。還有許多其他基於對象的語言。第一種這樣的語言被稱為“Simula”。它於 1960 年代在挪威發明。更重要的是,Simula中出現了“類”和“方法”的概念。以軟件開發的標準來看,“Simula”似乎是一門古老的語言,但任誰都能看出它與Java的“血緣”。面向對象編程原理 - 1您可能可以輕鬆閱讀用這種語言編寫的代碼,並粗略地解釋它的作用 :)

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;
本代碼示例代碼摘自Weekly-geekly的《Simula - 50 years of OOP》。如您所見,Java 與它的祖父並沒有太大區別:) 這是因為 Simula 的出現標誌著一個新概念的誕生:面向對象編程。維基百科這樣定義 OOP:“面向對象編程 (OOP) 是一種基於“對象”概念的編程範式,它可以包含數據,以字段(通常稱為屬性)的形式,以及代碼,以形式程序(通常稱為方法)。” 在我看來,這是一個非常好的定義。不久前您開始學習 Java,但是這個定義可能不包含任何您不知道的詞:) 今天 OOP 是最常見的編程方法論。除了Java,OOP 原則用於您可能聽說過的許多流行語言。例如,C++(積極用於遊戲開發)、Objective-C 和 Swift(用於為 Apple 設備編寫程序)、Python(在機器學習中最流行)、PHP(最流行的 Web 開發語言之一)、JavaScript(更容易說出它不用於什麼)和許多其他。那麼,OOP 的原則到底是什麼?我們會詳細告訴你。OOP 的原則是什麼?我們會詳細告訴你。OOP 的原則是什麼?我們會詳細告訴你。

面向對象原則

這些是基礎的基礎。4 個主要特徵共同構成了面向對象的編程範式。了解它們對於成為一名成功的程序員至關重要。

原則 1. 繼承

好消息:您已經了解 OOP 的一些原則!:) 我們已經在課程中遇到過幾次繼承,並且我們設法使用了它。繼承是一種機制,可讓您基於現有(父)類描述新類。這樣做時,新類借用了父類的屬性和功能。什麼是繼承,它提供了哪些優勢?最重要的是,代碼重用。父類中聲明的字段和方法可以在子類中使用。如果所有類型的汽車都有10個公共字段和5個相同的方法,則只需將它們移動到Auto父類。您可以毫無問題地在子類中使用它們。堅實的優勢:既有定量的(更少的代碼),也有定性的(類變得更簡單)。此外,繼承非常靈活——您可以添加後代所缺少的單獨功能(某些特定於特定類的字段或行為)。總的來說,就像在現實生活中一樣,我們都與我們的父母有些相似,但也與他們有所不同 :)

原則 2. 抽象

這是一個非常簡單的原則。抽象意味著確定事物的主要、最重要的特徵,同時丟棄任何次要和無關緊要的事物。無需重新發​​明輪子。讓我們回憶一下關於類的舊課中的一個例子。假設我們正在為公司員工創建一個文件系統。為了創建“僱員”對象,我們編寫了一個僱員類。在公司備案系統中描述它們的哪些特徵很重要?姓名、出生日期、SSN 和員工 ID。但我們不太可能需要員工的身高、眼睛顏色或頭髮顏色來進行此類記錄。公司不需要有關員工的此類信息。因此,在Employee類中,我們聲明了以下變量:, int age , int socialSecurityNumberint employeeId。我們抽象掉了不必要的信息,比如眼睛的顏色。但是,如果我們正在為模特經紀公司製作歸檔系統,情況就會發生巨大變化。模特的身高、眼睛顏色和頭髮顏色是重要的特徵,但她的 SSN 與我們絕對無關。因此,在Model類中,我們創建了以下變量:String heightString hairString eyes

原則 3. 封裝

我們已經遇到過這個。在 Java 中,封裝意味著限制讀取和更改數據的能力。如您所見,該術語基於“膠囊”一詞。我們將使用“膠囊”來隱藏一些我們不希望其他人更改的重要數據。這是現實生活中的一個簡單例子。你有名字和姓氏。你所有的朋友都認識他們。但他們無法更改您的名字或姓氏。我們可以說這樣做的過程被法院系統“封裝”了:您只能通過法院書記員更改您的姓氏,而且只有您自己可以這樣做。其他“用戶”對您的名字和姓氏具有“只讀”訪問權:) 另一個說明性示例是存放在家裡的現金。將它放在房間中央的顯眼位置並不是一個好主意。任何“用戶”(來到您家的人)都可以更改您的錢數,即他們可以拿走您的錢。還是封裝在保險櫃裡比較好。然後只有您才能訪問,並且只能使用特殊代碼。您已經使用過的明顯封裝示例是訪問修飾符(私有、公共等),以及 setter 和 getter。如果你不封裝Cat類的age字段,那麼任何人都可以寫:

Cat.age = -1000;
封裝機制讓我們用setter方法保護age字段,保證age不能設置為負數。

原則 4. 多態性

多態性是處理多種類型的能力,就好像它們是同一類型一樣。此外,對象的行為將根據它們的類型而有所不同。這聽起來很複雜嗎?讓我們現在就理解它。舉個最簡單的例子:動物。使用單個speak()方法和兩個子類—— CatDog創建一個Animal類。

public class Animal {

   public void speak() {
      
       System.out.println("Hello!");
   }
}

public class Dog extends Animal {
  
   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
現在我們將嘗試聲明一個Animal引用變量並為其 分配一個Dog對象。

public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
你認為會調用什麼方法?Animal.speak()Dog.speak()Dog類中的方法將被調用:Woof-woof!我們創建了一個Animal引用,但該對象的行為類似於Dog。如有必要,它可以表現得像貓、馬或其他動物。重要的是將特定的子類分配給一般的Animal引用變量。這是有道理的,因為所有的狗都是動物。這就是我們所說的“對象的行為會因類型而異”時的想法。如果我們創建了一個Cat對象......

public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
speak ()方法會顯示“Meow!” 但是,我們所說的“像處理同一類型一樣處理多種類型的能力”是什麼意思?這也很簡單。假設我們正在為動物創建一個理髮店。我們的理髮店應該能夠給任何動物修剪,所以我們創建了一個帶有Animal參數(正在理髮的動物) 的trim()方法。

public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!"); 
   }
}
現在我們可以將CatDog對像傳遞給trim()方法!

public static void main(String[] args) {

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

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
這是一個明顯的例子:AnimalBarbershop類與CatDog類型一起工作,就好像它們是同一類型一樣。同時,CatDog有不同的行為:他們說話的方式各不相同。

為什麼我們需要 OOP?

為什麼 OOP 會作為一個新的編程概念出現?程序員擁有功能性工具,例如過程語言。是什麼促使他們發明了一些全新的東西?最重要的是,他們面臨的任務非常複雜。如果 60 年前程序員的任務類似於“評估一些數學表達式”,那麼現在它可能類似於“根據玩家在 A、B、C、DE 點做出的決定的組合,為遊戲 STALKER 實現 7 個不同的結局, 以及遊戲中的 F。” 如您所見,在過去幾十年中,任務顯然變得更加複雜。結果,數據類型變得更加複雜。這也是OOP出現的另一個原因。可以使用普通原語輕鬆計算數學表達式。這裡不需要對象。但是如果不使用自定義類,遊戲結局的任務甚至很難描述。也就是說,使用類和對象來描述它非常容易。顯然,我們需要幾個類:Game、Stalker、Ending、PlayerDecision、GameEvent 等等。換句話說,即使沒有開始解決問題,我們也可以很容易地在腦海中“勾勒出”一個解決方案。任務越來越複雜,迫使程序員將它們分成幾部分。但這在過程編程中並不是那麼容易做到。一個程序通常就像一棵樹,有很多分支代表所有可能的執行路徑。根據某些條件,執行程序的一個分支或另一個分支。對於小程序來說,這很方便,但是很難把一個大問題分成幾個部分。這是 OOP 出現的另一個原因。這種範式使程序員能夠將程序劃分為一堆“模塊”(類),每個模塊都完成自己的部分工作。通過相互交互,所有對象完成我們程序的工作。另外,我們可以在程序的其他地方復用我們的代碼,這也節省了大量的時間。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION