開發語言中關于面向對象和面向過程的筆記
- 市面主流語言分類
- 面向過程
- 面向對象
市面主流語言分類
- 面向過程編程(Procedural Programming):C語言;
- 面向對象編程語言(Object-Oriented Programming, OOP) :Java、C++、C#、Python;
面向過程
面向過程的程序可以視為一系列線性執行的步驟(函數或子程序),通過控制流語句(順序、循環、分支)組織邏輯。
其中,
1、面向過程的變成語言數據和操作是分離的,數據是存儲在變量中的,函數獨立操作這些數據。
也就是定義的子函數與變量是相互獨立的,通過函數調用傳遞數據。
例如,先定義不同功能的函數,然后在主函數中調用該子函數,子函數的入參在主函數中定義。
#include <stdio.h>// 定義獨立函數操作數據
float circle_area(float radius) {return 3.14 * radius * radius;
}float rectangle_area(float width, float height) {return width * height;
}int main() {// 數據與函數分離float r = 5.0;float w = 4.0, h = 6.0;printf("Circle Area: %.2f\n", circle_area(r)); // 輸出 78.50printf("Rectangle Area: %.2f\n", rectangle_area(w, h)); // 輸出 24.00return 0;
}
面向過程的變成方法,都是從主函數開始,逐步分解任務為子過程,也就是自頂向下設計
所以,面向過程的變成的基本單元是函數(過程)
面向過程是步驟導向
面向對象
面向對象的程序由相互作用的對象構成,每個對象包含數據(屬性)和行為(方法)。
// 這里定義了一個類Circle,在這個類里封裝了一個變量radius和一個行為(方法)getArea。
class Circle { private double radius; // 半徑被保護 【這里的變量是private,意味著這是一個私有變量,私有意味著只能在Circle類內部訪問,外部無法直接訪問。所以稱為“半徑被保護”,這里的面向對象封裝起到了數據保護的作用】//我們將半徑設為私有,這樣外部代碼不能直接修改半徑(除非通過構造方法,但構造方法只在創建對象時調用一次)public Circle(double r) { this.radius = r;this.radius = r; } //【這里是一個公共的構造方法,這個方法的參數是r,用于在創建Circle對象時初始化半徑(創建Circle類的對象)。通過這個公共方法的參數r,將r的值傳遞給成員變量radius,//這里的this是指當前對象,也就是使用類創建對象后,這個對象就有個這個變量,通過構造函數對這個變量進行賦值。】//【先定義類,然后類中定義構造函數,構造函數用于定義新的方法,方法通過構造函數對變量進行賦值,然后再使用定義的對象調用類中的方法】public double getArea() { // 對象自己計算【公共方法,無參數】 ,這里是行為封裝 ,邏輯封裝在內部,外部只需要調用該方法return 3.14 * radius * radius; }
} // 這里使用 Circle 類創建了對象myCircle
Circle myCircle = new Circle(5.0); //【new用來創建新的對象,這里使用構造方法Circle,將5.0傳遞給了r。創建的對象被賦值給了Circle 類型的變量myCircle 】
//【這里需要注意,在這里進行對象初始化時即確定半徑值,后續無法直接修改,如果要修改需要創建setRadius 方法】
//對象的創建步驟為:1、new 在堆內存分配空間,創建 Circle 對象實例。2、調用構造方法 Circle(5.0),初始化 radius = 5.0。3、對象地址賦值給引用變量 myCircle(棧內存存儲該地址)。double area = myCircle.getArea(); // 告訴圓:"把你的面積給我"【這里的myCircle 是個對象,通過對象調用了類中的方法getArea】
//【這個例子展示了面向對象編程中的**封裝特性**:將數據(半徑)隱藏在對象內部,通過公共方法提供對數據的操作(計算面積)。外部代碼只需要知道如何調用方法,而不需要知道內部實現細節。】
在這個例子中,定義了類Circle ,在類中定義了一個私有成員變量radius,一個構造方法Circle,一個成員方法getArea。
**【堆與棧需單獨分析】**
總結面向對象的編程
類是較為頂層的設計,在類中定義各種成員,通過類定義這個類的對象。
上面例子中,通過私有的變量+公有的方法,僅暴漏接口,保障了數據的安全性,私有變量只有創建方法時定義,通過構造函數。
通俗的理解:
面向過程:是廚師,自己按步驟做菜。
第1步:拿2個番茄切塊
第2步:打3個雞蛋攪勻
第3步:開火倒油,炒雞蛋后盛出
第4步:炒番茄,加雞蛋混合
第5步:放鹽出鍋
面向對象:是餐廳老板,開一家餐廳
招專業員工(創建對象):
🧑?🍳 廚師對象:技能 炒菜()
🧅 番茄對象:屬性「顏色=紅」,行為「被切塊」
🥚 雞蛋對象:屬性「數量=3」,行為「被打散」
發號施令(對象交互)
廚師.處理(番茄); // 番茄自己執行"切塊"
廚師.處理(雞蛋); // 雞蛋自己執行"打散"
廚師.炒(番茄, 雞蛋); // 廚師調用"炒"方法
最后再做一次分析
// 抽象父類:定義公共接口
//定義抽象類Shape,抽象類不可實例化,也就不不能創建對象
//通過抽象類定義了一個模版,一個形狀的模版(也可以是一個汽車的模版)
abstract class Shape {public abstract double area();//抽象類中定義抽象方法,這個方法在子類中必須被實現
}// 子類繼承并實現多態
class Circle extends Shape {//子類Circle 繼承了父類Shape ,因為Shape中包含抽象方法,因此在這個子類中必須實現該方法,也就是必須包含方法體
//一個普通類繼承“形狀”這個抽象類,定義了一個圓形,該類包含了圓形的具體實現,根據抽象類的要求,必須實現該形狀的面積。private double radius; // 封裝數據。封裝私有成員變量public Circle(double radius) {//構造函數this.radius = radius;}@Override//重寫父類的方法area,可用戶后續的多態實現,需要使用哪個便創建哪個子類的對象,結果將根據子類的不同而不同public double area() { // 多態實現。對繼承的父類中的抽象方法進行實現。return Math.PI * radius * radius;}//方法體
}class Rectangle extends Shape {//同理,這是定義了一個長方形類,該類繼承了抽象類“形狀”,因此在這個長方形中“面積”這個方法必須被實現private double width, height;//定義私有成員變量public Rectangle(double width, double height) {//長方形這個類的構造函數this.width = width;this.height = height;}@Overridepublic double area() {//實現抽象方法“面積”return width * height;}
}public class Main {//定義一個公有的類Mainpublic static void main(String[] args) {//定義了main方法Shape circle = new Circle(5.0); // 父類引用指向子類對象。創建了一個對象circle ,這里的構造函數Circle引用了父類Shape的子類Circle Shape rect = new Rectangle(4.0, 6.0);//同理,再創建一個對象rect,引用了子類//多態:通過父類引用調用子類重寫的方法,實際執行的是子類的方法。 System.out.println("Circle Area: " + circle.area()); // 78.54。打印對象circle的方法areaSystem.out.println("Rectangle Area: " + rect.area()); // 24.00}
}
面向對象的編程的基本單元是對象(數據 + 方法)
面向對象是角色協作
上面通過對實際代碼的解析,嘗試理解java的面向對象開發,對于某一個任務可以通過定義類來定義功能,后續可以直接通過構造函數創建該類的對象,對象通過調用具體方法來完成對單功能的實現。
也可以其他類通過創建該類的對象,通過構造函數,然后調用該對象中的方法,以實現具體目標
例如,這邊通過多單元分工實現了多個功能類的開發,開發完成后統一由一個人創建一個類來創建各個類的對象,通過該對象調用方法達到實現某功能的目標。
也就是面向對象的編程。
整體上看,面向過程的編程更適合單體作戰,一個人完成重頭到尾的任務。面向過程的編程更適合集群作戰,每個角色負責不同的任務,通過多體交互完成最終任務。