Szukaj…


Uwagi

Programowanie obiektowe (OOP) to paradygmat programowania oparty na koncepcji „obiektów”, które mogą zawierać dane w postaci pól, często nazywanych atrybutami; i kod w postaci procedur, często znanych jako metody.

Wprowadzenie

OOP - Object Oriented Programming jest obecnie szeroko stosowanym paradygmatem programowania. W OOP modelujemy problemy ze świata rzeczywistego za pomocą obiektów i zachowań, aby programowo je rozwiązać.

Istnieją cztery główne koncepcje OOP

  1. Dziedzictwo
  2. Wielopostaciowość
  3. Abstrakcja
  4. Kapsułkowanie

Te cztery koncepcje razem są wykorzystywane do opracowywania programów w OOP.

Istnieją różne języki, które wspierają programowanie obiektowe. Najpopularniejsze języki to

  • C ++
  • Jawa
  • DO#
  • Python (Python nie jest w pełni zorientowany obiektowo, ale ma większość funkcji OOP)

Wprowadzenie do OOP

Wprowadzenie

Programowanie obiektowe (zwane głównie OOP) to paradygmat programowania do rozwiązywania problemów.
Piękno programu OO (obiektowego) polega na tym, że myślimy o nim jako o grupie obiektów komunikujących się ze sobą, a nie o sekwencyjnym skrypcie wykonującym określone polecenia.

Istnieje wiele języków programowania, które obsługują OOP, niektóre z popularnych to:

  • Jawa
  • C ++
  • do#

Python jest również znany z obsługi OOP, ale brakuje mu kilku właściwości.


Terminologia OOP

Najbardziej podstawowym terminem w OOP jest klasa .
Klasa jest zasadniczo obiektem , który ma stan i działa zgodnie ze swoim stanem.

Innym ważnym terminem jest instancja .
Pomyśl o klasie jako szablonie używanym do tworzenia własnych instancji. Klasa jest szablonem, a instancja (y) to konkretne obiekty.

Instancja utworzona z klasy A jest zwykle określana jako „typ A”, dokładnie tak jak typ 5 to int, a typ „abcd” to ciąg znaków .

Przykład tworzenia instancji o nazwie insance1 typu (class) ClassA :

Jawa

ClassA instance1 = new ClassA();

C ++

ClassA instance1;

lub

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

Pyton

instance1 = ClassA()

Jak widać w powyższym przykładzie, we wszystkich przypadkach wymieniono nazwę klasy, a po niej były puste nawiasy (z wyjątkiem C ++, gdzie jeśli są puste, nawiasy można usunąć). W tych nawiasach możemy przekazywać arguments do konstruktora naszej klasy.

Konstruktor to metoda klasy wywoływana za każdym razem, gdy tworzona jest instancja. Może przyjmować argumenty lub nie. Jeśli programista nie określi żadnego konstruktora dla klasy, którą budują, zostanie utworzony pusty konstruktor (konstruktor, który nic nie robi).
W większości języków konstruktor jest definiowany jako metoda bez definiowania typu zwracanego i o tej samej nazwie klasy (przykład w kilku sekcjach).

Przykład tworzenia instancji o nazwie b1 typu (klasa) ClassB . Konstruktor ClassB trwa jeden argument typu int:

Jawa

ClassA instance1 = new ClassA(5);

lub

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

C ++

ClassA instance1(5);

Pyton

instance1 = ClassA(5)

Jak widać, proces tworzenia instancji jest bardzo podobny do procesu wywoływania funkcji.


Funkcje a metody

Zarówno funkcje, jak i metody są bardzo podobne, ale w projektowaniu obiektowym (OOD) każde z nich ma swoje własne znaczenie.
Metoda jest operacją wykonywaną na instancji klasy. Sama metoda zwykle wykorzystuje stan instancji do działania.
Tymczasem funkcja należy do klasy, a nie do konkretnej instancji. Oznacza to, że nie wykorzystuje stanu klasy ani żadnych danych przechowywanych w instancji.

Odtąd będziemy pokazywać nasze przykłady tylko w Javie, ponieważ OOP jest bardzo jasne w tym języku, ale te same zasady działają w każdym innym języku OOP.

W Javie funkcja ma w definicji słowo static , takie jak:

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

Oznacza to, że możesz wywołać go z dowolnego miejsca w skrypcie.

// 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));

Kiedy wywołujemy funkcję z innego pliku, używamy nazwy klasy (w Javie jest to również nazwa pliku), do którego należy, daje to intuicję, że funkcja należy do klasy, a nie do żadnej z jej instancji.

W przeciwieństwie do tego możemy zdefiniować metodę w klasie A w następujący sposób:

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

Po tej deklinacji możemy wywołać tę metodę w następujący sposób:

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

Tutaj musieliśmy utworzyć instancję klasy A , aby wywołać jej metodę odejmowania. Zauważ, że NIE MOŻEMY wykonać następujących czynności:

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

Ten wiersz spowoduje błąd kompilacji, narzekając, że nazwaliśmy tę metodę niestatyczną bez instancji.


Korzystanie ze stanu klasy

Załóżmy, że chcemy ponownie wdrożyć naszą metodę odejmowania , ale tym razem zawsze chcemy odjąć tę samą liczbę (dla każdej instancji). Możemy stworzyć następującą klasę:

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
    }
}

Po uruchomieniu tego kodu tworzona jest nowa instancja o nazwie b klasy ClassB, a jej konstruktor jest zasilany wartością 5 .
Konstruktor bierze teraz podaną sumę_danych i przechowuje ją jako swoje prywatne pole, zwane także sub_kwotą (ta konwencja jest bardzo znana w Javie, aby nazwać argumenty tak samo jak pola).
Następnie wypisujemy do konsoli wynik wywołania metody odejmij b na wartość 3 .

Zauważ, że przy implementacji odejmowania tego nie używamy this. jak w konstruktorze.
W Javie, this musi być napisane tylko, gdy istnieje inna zmienna o tej samej nazwie określonej w tym zakresie. To samo działa z self Pythona.
Kiedy więc używamy sub_amount w odejmowaniu, odwołujemy się do prywatnego pola, które jest różne dla każdej klasy.

Kolejny przykład do podkreślenia.
Po prostu zmieńmy główną funkcję w powyższym kodzie na:

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

Jak widzimy, b1 i b2 są niezależne i każdy ma swój własny stan .


Interfejsy i dziedziczenie

Interfejs to umowa, która określa, jakie metody będzie miała klasa, a tym samym jej możliwości. Interfejs nie ma implementacji, określa jedynie, co należy zrobić.
Przykładem w Javie byłoby:

interface Printalbe {
    public void print();
}

Interfejs Printalbe definiuje metodę o nazwie print, ale nie podaje jej implementacji (dość dziwne jak na Javę). Każda klasa, która deklaruje się jako implementing ten interfejs, musi zapewnić implementację metody draw. Na przykład:

class Person implements Printalbe {

    private String name;

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

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

Gdyby osoba zadeklarowała się jako implementująca program Drawable, ale nie zapewniła implementacji do wydrukowania , wystąpiłby błąd kompilacji i program nie skompilowałby się.

Dziedziczenie to termin wskazujący na klasę rozszerzającą inną klasę. Załóżmy na przykład, że mamy teraz osobę w wieku. Jednym ze sposobów na zaimplementowanie takiej osoby byłoby skopiowanie klasy Person i napisanie nowej klasy o nazwie AgedPerson, która ma te same pola i metody, ale ma inną właściwość.
Byłoby to okropne, ponieważ kopiujemy cały nasz kod, aby dodać prostą funkcję do naszej klasy.
Możemy użyć dziedziczenia, aby odziedziczyć po Osobie, a tym samym uzyskać wszystkie jego funkcje, a następnie ulepszyć je dzięki naszej nowej funkcji, na przykład:

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);
    }
}

Dzieje się kilka nowych rzeczy:

  • Użyliśmy zapisanych extends słowa, aby wskazać, że dziedziczymy od Person (a także jego implementacji do Printable , więc nie musimy ponownie deklarować implementing Printable ).
  • Użyliśmy słowa „ super aby wywołać konstruktora Osoby .
  • Zastąpiliśmy nową metodę drukowania osoby .

To robi się dość techniczne w Javie, więc nie będę zagłębiał się w ten temat. Wspomnę jednak, że istnieje wiele ekstremalnych przypadków, które należy nauczyć się o dziedziczeniu i interfejsach przed rozpoczęciem ich używania. Na przykład, które metody i funkcje są dziedziczone? Co dzieje się z polami prywatnymi / publicznymi / chronionymi podczas dziedziczenia po klasie? i tak dalej.

Klasa abstrakcyjna

Klasa abstrakcyjna jest dość zaawansowanym terminem w OOP, który opisuje połączenie obu interfejsów i dziedziczenia. Pozwala napisać klasę, która ma zarówno zaimplementowane, jak i niezaimplementowane metody / funkcje. W Javie odbywa się to za pomocą słowa kluczowego abstract i nie wyjaśnię tego bardziej niż szybki przykład:

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);
    }
}

Uwaga: final słowo kluczowe stwierdza, że nie można zastąpić tej metody podczas dziedziczenia po tej klasie. Jeśli klasa zostanie ogłoszona jako ostateczna, żadna klasa nie będzie w stanie po niej dziedziczyć.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow