更新時間:2021-08-25 10:49:51 來源:動力節點 瀏覽1120次
面向對象編程 (OOP) 是一種依賴于類和對象概念的編程范式。它用于將軟件程序構建為簡單、可重用的代碼藍圖(通常稱為類),用于創建對象的單個實例。有許多面向對象的編程語言,包括 JavaScript、C++、Java和Python。
一類是用于創建更具體的,具體對象的抽象藍圖。類通常代表廣泛的類別,例如Car或Dog共享屬性。這些類定義了此類型的實例將具有哪些屬性,例如color,但不定義特定對象的這些屬性的值。
類還可以包含函數,稱為僅對該類型的對象可用的方法。這些函數在類中定義,并執行一些對特定類型對象有幫助的操作。
例如,我們的Car類可能有一個方法repaint來改變color我們汽車的屬性。這個函數只對 type 的對象有用Car,所以我們在Car類中聲明它,從而使它成為一個方法。
類模板用作創建單個對象的藍圖。這些代表抽象類的特定示例,例如myCar或goldenRetriever。對于類中定義的屬性,每個對象都可以具有唯一值。
例如,假設我們創建一個類,Car以包含所有汽車必須具備的特性color,brand和model。然后我們創建一個Car類型對象的實例,myCar來代表我的特定汽車。
然后我們可以設置類中定義的屬性值來描述我的汽車,而不會影響其他對象或類模板。
然后我們可以重用這個類來表示任意數量的汽車。
OOP 將復雜事物建模為可重現的簡單結構
可重用,OOP 對象可以跨程序使用
允許通過多態實現特定于類的行為
更容易調試,類通常包含所有適用的信息
安全,通過封裝保護信息
讓我們考慮一個現實世界的問題,從概念上設計一個 OOP 軟件程序。
想象一下,經營一個有數百只寵物的狗訓練營,您必須跟蹤每只寵物的姓名、年齡和參加日期。您將如何設計簡單、可重復使用的軟件來為狗建模?
有數百只狗,為每只狗編寫唯一代碼將是低效的。下面我們將看到對象rufus和fluffy.
//Object of one individual dog
var rufus = {
name: "Rufus",
birthday: "2/1/2017",
age: function() {
return Date.now() - this.birthday;
},
attendance: 0
}
//Object of second individual dog
var fluffy = {
name: "Fluffy",
birthday: "1/12/2019",
age: function() {
return Date.now() - this.birthday;
},
attendance: 0
}
正如你在上面看到的,兩個對象之間有很多重復的代碼。該age()函數出現在每個對象中。由于我們希望每只狗都有相同的信息,因此我們可以使用對象和類來代替。
將相關信息組合在一起形成類結構使代碼更短且更易于維護。
在養狗示例中,以下是程序員如何考慮組織 OOP:
為所有狗創建一個父類,作為所有狗都將擁有的信息和行為(方法)的藍圖,無論類型如何。
在通用父藍圖下創建子類來表示狗的不同子類別。
向子類添加獨特的屬性和行為以表示差異
從代表該子組中的狗的子類創建對象
下圖展示了如何設計 OOP 程序:將相關數據和行為組合在一起形成一個簡單的模板,然后為專門的數據和行為創建子組。
該Dog班是一個通用模板,只包含有關數據,并適用于所有的狗行為的結構。
然后我們創建兩個子類Dog,HerdingDog和TrackingDog。它們具有Dog( bark())的遺傳行為,但也具有該亞型狗獨有的行為。
最后,我們創建該HerdingDog類型的對象來表示單個狗Fluffy和Maisel。
我們還可以創建這樣的對象Rufus,該對象適合廣泛的類 ,Dog但不適合HerdingDog或TrackingDog。
接下來,我們將深入了解上面使用的 OOP 程序的每個基本構建塊:
班級
對象
方法
屬性
班級
簡而言之,類本質上是用戶定義的數據類型。類是我們為方法和屬性的結構創建藍圖的地方。單個對象是從該藍圖實例化或創建的。
類包含屬性字段和行為方法。在我們的Dog類示例中,屬性包括name& birthday,而方法包括bark()和updateAttendance()。
下面的代碼片段演示了如何Dog使用JavaScript語言對類進行編程。
class Dog {
constructor(name, birthday) {
this.name = name;
this.birthday = birthday;
}
//Declare private variables
_attendance = 0;
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return Date.now() - this.birthday;
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
請記住,該類是用于建模狗的模板,并且對象是從代表單個現實世界事物的類實例化的。
對象
當然 OOP 包括對象!對象是使用特定數據創建的類的實例,例如在下面的代碼片段中Rufus是Dog類的實例。
class Dog {
constructor(name, birthday) {
this.name = name;
this.birthday = birthday;
}
//Declare private variables
_attendance = 0;
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return Date.now() - this.birthday;
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
//instantiate a new object of the Dog class, and individual dog named Rufus
const rufus = new Dog("Rufus", "2/1/2017");
當新類Dog被調用時:
創建了一個名為的新對象 rufus
構造函數運行name&birthday參數,并分配值
屬性
屬性是存儲的信息。屬性在Class模板中定義。當對象被實例化時,單個對象包含存儲在 Attributes 字段中的數據。
對象的狀態由對象屬性字段中的數據定義。例如,在寵物營地,一只小狗和一只狗可能受到不同的對待。生日可以定義對象的狀態,并允許軟件以不同的方式處理不同年齡的狗。
方法
方法代表行為。方法執行動作;方法可能會返回有關對象的信息,或更新對象的數據。方法的代碼在類定義中定義。
當單個對象被實例化時,這些對象可以調用類中定義的方法。在下面的代碼片段中,bark方法是在Dog類中定義的,bark()方法是在Rufus對象上調用的。
class Dog {
//Declare protected (private) fields
_attendance = 0;
constructor(name, birthday) {
this.namee = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
方法經常修改、更新或刪除數據。方法不必更新數據。例如,該bark()方法不會更新任何數據,因為 barking 不會修改類的任何屬性Dog:name或birthday。
該updateAttendance()方法增加了Dog參加寵物訓練營的一天。出勤屬性對于在月底跟蹤計費所有者很重要。
方法是程序員促進可重用性并將功能封裝在對象中的方式。這種可重用性在調試時是一個很大的好處。如果出現錯誤,只有一個地方可以找到并修復它,而不是很多地方。
下劃線 in_attendance表示該變量是受保護的,不應直接修改。該updateAttendance()方法用于更改_attendance.
面向對象編程的四大支柱是:
繼承:子類繼承父類的數據和行為
封裝:在對象中包含信息,只暴露選定的信息
抽象:只公開訪問對象的高級公共方法
多態性:許多方法可以完成相同的任務
遺產
繼承允許類繼承其他類的特性。換句話說,父類將屬性和行為擴展到子類。繼承支持可重用性。
如果在父類中定義了基本屬性和行為,則可以創建子類來擴展父類的功能,并添加額外的屬性和行為。
例如,牧羊犬具有獨特的放牧能力。換句話說,所有的牧羊犬都是狗,但并非所有的狗都是牧羊犬。我們通過HerdingDog從父類創建一個子類來表示這種差異Dog,然后添加獨特的herd()行為。
繼承的好處是程序可以創建一個通用的父類,然后根據需要創建更具體的子類。這簡化了整體編程,因為子類無需Dog多次重新創建類的結構,而是自動獲得對其父類中功能的訪問權限。
在下面的代碼片段中,子類HerdingDog繼承了bark父類Dog的方法,子類添加了一個額外的方法,herd()。
//Parent class Dog
class Dog{
//Declare protected (private) fields
_attendance = 0;
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
constructor(name, birthday) {
super(name);
super(birthday);
}
herd() {
//additional method for HerdingDog child class
return console.log("Stay together!")
}
}
請注意,HerdingDog該類沒有bark()方法的副本,它繼承bark()了父Dog類中定義的方法。
當代碼調用fluffy.bark()方法時,該bark()方法會沿著子類到父類的鏈向上走,以找到bark定義方法的位置。
//Parent class Dog
class Dog{
//Declare protected (private) fields
_attendance = 0;
constructor(namee, birthday) {
this.name = name;
this.birthday = birthday;
}
getAge() {
//Getter
return this.calcAge();
}
calcAge() {
//calculate age using today's date and birthday
return this.calcAge();
}
bark() {
return console.log("Woof!");
}
updateAttendance() {
//add a day to the dog's attendance days at the petsitters
this._attendance++;
}
}
//Child class HerdingDog, inherits from parent Dog
class HerdingDog extends Dog {
constructor(name, birthday) {
super(name);
super(birthday);
}
herd() {
//additional method for HerdingDog child class
return console.log("Stay together!")
}
}
//instantiate a new HerdingDog object
const fluffy = new HerdingDog("Fluffy", "1/12/2019");
fluffy.bark();
在 JavaScript 中,繼承也稱為原型設計。原型對象充當另一個對象從中繼承屬性和行為的模板。可以有多個原型對象模板,創建一個原型鏈。
這與父/子繼承的概念相同。繼承是從父到子的。在我們的示例中,所有三只狗都可以吠叫,但只有 Maisel 和 Fluffy 可以放牧。
該herd()方法在子HerdingDog類中定義,因此從該類實例化的兩個對象Maisel和可以訪問該方法。FluffyHerdingDogherd()
Rufus 是從父類實例化的對象Dog,因此 Rufus 只能訪問該bark()方法。
封裝
封裝意味著將所有重要信息包含在一個對象內部,并且只將選定的信息暴露給外部世界。屬性和行為由類模板內的代碼定義。
然后,當從類中實例化對象時,數據和方法被封裝在該對象中。封裝將內部的軟件代碼實現隱藏在一個類中,隱藏了內部對象的內部數據。
封裝需要將某些字段定義為私有字段,將某些字段定義為公共字段。
私有/內部接口:方法和屬性,可從同一類的其他方法訪問。
公共/外部接口:方法和屬性,也可以從類外部訪問。
抽象
抽象意味著用戶僅與對象的選定屬性和方法進行交互。抽象使用簡化的高級工具來訪問復雜的對象。
用簡單的事物來表示復雜性
對用戶隱藏復雜的細節
抽象是使用簡單的類來表示復雜性。抽象是封裝的擴展。例如,您不必了解發動機如何工作來驅動汽車的所有細節。
駕駛員只使用一小部分工具:如油門踏板、剎車、方向盤、閃光燈。工程對司機是隱藏的。為了讓汽車運轉起來,很多部件都必須在引擎蓋下工作,但是將這些信息暴露給駕駛員會很危險地分散注意力。
抽象也起著重要的安全作用。通過只顯示選定的數據片段,并且只允許通過類訪問數據和通過方法修改數據,我們可以保護數據不被暴露。繼續以汽車為例,您不希望在駕駛汽車時打開油箱。
抽象的好處總結如下:
簡單、高級的用戶界面
復雜代碼被隱藏
安全
更輕松的軟件維護
代碼更新很少改變抽象
多態性
多態意味著設計對象來共享行為。使用繼承,對象可以覆蓋共享的父行為,具有特定的子行為。多態允許同一個方法以兩種方式執行不同的行為:方法覆蓋和方法重載。
以上就是動力節點小編介紹的"面向對象編程:OOP深入解釋",希望對大家有幫助,想了解更多可查看Java教程。動力節點在線學習教程,針對沒有任何Java基礎的讀者學習,讓你從入門到精通,主要介紹了一些Java基礎的核心知識,讓同學們更好更方便的學習和了解Java編程,感興趣的同學可以關注一下。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習