oopoop入門


備註

面向對象編程(OOP)是一種基於“對象”概念的編程範例,它可能包含字段形式的數據,通常稱為屬性;代碼,以程序的形式,通常稱為方法。

介紹

OOP - 面向對象編程是目前廣泛使用的編程範例。在OOP中,我們使用對象和行為來模擬現實世界中的問題,以便以編程方式解決它們。

有四個主要的OOP概念

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

這四個概念一起用於開發OOP程序。

有各種語言可以支持面向對象編程。最流行的語言是

  • C ++
  • Java的
  • C#
  • Python(Python不完全面向對象,但具有大部分OOP功能)

OOP簡介

Intoduction

面向對象編程(主要稱為OOP)是解決問題的編程範例。
OO(面向對象)程序的美妙之處在於,我們將程序視為一組彼此通信的對象,而不是遵循特定順序的順序腳本。

有很多支持OOP的編程語言,一些流行的是:

  • Java的
  • C ++
  • C#

眾所周知,Python也支持OOP,但它缺少一些屬性。


OOP術語

OOP中最基本的術語是一個
一個類基本上是一個對象 ,它有一個狀態,它根據它的狀態工作。

另一個重要的術語是一個實例
將類視為用於創建自身實例的模板。該類是一個模板,實例是具體的對象。

從類A創建的實例通常被稱為“類型A”,類似於5的類型是int“abcd”的類型是字符串

創建名為insance1的類型(類) ClassA的實例的示例:

Java的

ClassA instance1 = new ClassA();
 

C ++

ClassA instance1;
 

要么

ClassA *instance1 = new ClassA(); # On the heap
 

蟒蛇

instance1 = ClassA()
 

正如您在上面的示例中所看到的,在所有情況下都提到了類的名稱,之後有空括號(C ++除外,如果它們為空,則可以刪除括號)。在這些括號中,我們可以將arguments 傳遞給我們類的構造函數

構造函數是每次創建實例時調用的類的方法。它既可以參與也可以不論證。如果程序員沒有為他們構建的類指定任何構造函數,那麼將創建一個空構造函數(一個什麼都不做的構造函數)。
在大多數語言中,構造函數被定義為一種方法,沒有定義其返回類型和類的相同名稱(在幾個部分中的示例)。

創建名為b1的類型(類) ClassB的實例的示例。 ClassB的構造函數接受一個int類型的參數:

Java的

ClassA instance1 = new ClassA(5);
 

要么

int i = 5;
ClassA instance1 = new ClassA(i);
 

C ++

ClassA instance1(5);
 

蟒蛇

instance1 = ClassA(5)
 

如您所見,創建實例的過程與調用函數的過程非常相似。


功能與方法

功能和方法都非常相似,但在面向對象設計(OOD)中它們各自都有其自身的含義。
方法是對類的實例執行的操作。該方法本身通常使用實例的狀態來操作。
同時,函數屬於類而不屬於特定實例。這意味著它不使用類的狀態或實例中存儲的任何數據。

從現在開始,我們將僅在Java中展示我們的示例,因為OOP在這種語言中非常清晰,但是相同的原則適用於任何其他OOP語言。

在Java中,函數在其定義中包含單詞static ,如下所示:

// File's name is ClassA
public static int add(int a, int b) {
    return a + b;
}
 

這意味著您可以從腳本中的任何位置調用它。

// From the same file
System.out.println(add(3, 5));

// From another file in the same package (or after imported)
System.out.println(ClassA.add(3, 5));
 

當我們從另一個文件調用該函數時,我們使用它所屬的類的名稱(在Java中,這也是文件的名稱),這給出了函數屬於類而不是它的任何實例的直覺。

相比之下,我們可以像這樣在ClassA中定義一個方法:

// File's name is ClassA
public int subtract(int a, int b){
    return a - b;
}
 

在這個decleration之後我們可以像這樣調用這個方法:

ClassA a = new ClassA();
System.out.println(a.subtract(3, 5));
 

這裡我們需要創建一個ClassA實例,以便調用它的方法減法。請注意,我們不能執行以下操作:

System.out.println(ClassA.subtract(3, 5));
 

這行會產生一個編譯錯誤,抱怨我們在沒有實例的情況下調用了這個非靜態方法。


使用類的狀態

讓我們假設我們想再次實現我們的減法方法,但這次我們總是想減去相同的數字(對於每個實例)。我們可以創建以下類:

class ClassB {

    private int sub_amount;

    public ClassB(int sub_amount) {
        this.sub_amount = sub_amount;
    }

    public int subtract(int a) {
        return a - sub_amount;
    }

    public static void main(String[] args) {
        ClassB b = new ClassB(5);
        System.out.println(b.subtract(3)); // Ouput is -2
    }
}
 

當我們運行這段代碼,一個新的實例命名為BClassB的創建和它的構造被饋送值5。
構造函數現在接受給定的sub_amount並將其存儲為自己的私有字段,也稱為sub_amount (此約定在Java中非常有名,以將參數命名為與字段相同)。
之後,我們打印到控制台調用方法的結果減去 b的值為3

請注意,在執行減法時我們不使用this. 就像在構造函數中一樣。
在Java中, this 只需要在有與該範圍內定義的另一個同名變量被寫入。這同樣適用於Python的self
因此,當我們在減法中使用sub_amount時,我們引用每個類不同的私有字段。

另一個強調的例子。
我們只需將上面代碼中的main函數更改為:

ClassB b1 = new ClassB(1);
ClassB b2 = new ClassB(2);

System.out.println(b1.subtract(10)); // Output is 9
System.out.println(b2.subtract(10)); // Output is 8
 

我們可以看到, b1b2是獨立的,每個都有自己的狀態


接口和繼承

接口是一個契約,它定義了一個類將具有哪些方法,從而定義它的功能。接口沒有實現,它只定義了需要完成的操作。
Java中的一個例子是:

interface Printalbe {
    public void print();
}
 

Printalbe接口定義了一個名為print的方法,但它沒有給出它的實現(對於Java來說非常奇怪)。聲明自己implementing 此接口的每個類都必須為draw方法提供實現。例如:

class Person implements Printalbe {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void print() {
        System.out.println(name);
    }
}
 

如果Person聲明自己實現Drawable但沒有提供打印實現,則會出現編譯錯誤,程序無法編譯。

繼承是指向擴展另一個類的類的術語。例如,假設我們現在有一個有年齡的人。實現這樣的人的一種方法是複制Person類並編寫一個名為AgedPerson的新類,它具有相同的字段和方法,但它有另一個屬性-age。
這很糟糕,因為我們複製整個代碼只是為了給我們的類添加一個簡單的特性。
我們可以使用繼承繼承Person ,從而獲得它的所有功能,然後使用我們的新功能增強它們,如下所示:

class AgedPerson extends Person {

    private int age;

    public AgedPerson(String name, int age) {
        super(name);
        this.age = age;
    }

    public void print() {
        System.out.println("Name: " + name + ", age:" + age);
    }
}
 

有一些新的事情發生:

  • 我們使用保存的單詞extends 來表示我們繼承自Person(以及它的實現到Printable ,因此我們不需要再次聲明implementing Printable )。
  • 我們所使用的保存字super 調用Person的構造函數。
  • 我們用一個新的覆蓋了Person打印方法。

這是非常熟悉的Java技術,所以我不會深入研究這個主題。但是我會提到在開始使用它們之前應該學習很多關於繼承和接口的極端情況。例如,哪些方法和函數是繼承的?從類繼承時,私有/公共/受保護字段會發生什麼?等等。

抽像類

抽像類在OOP中是非常高級的術語,它描述了接口和繼承的組合。它允許你編寫一個具有已實現和未實現的方法/函數的類。在Java中,這是通過使用關鍵字abstract ,我不會更多地解釋它是一個簡單的例子:

abstract class AbstractIntStack {

    abstract public void push(int element);

    abstract public void pop();

    abstract public int top();

    final public void replaceTop(int element) {
        pop();
        push(element);
    }
}
 

注意: final 關鍵字表示從此類繼承時無法覆蓋此方法。如果一個類被聲明為final,那麼任何類都不能從它繼承。