Delegacja (programowanie obiektowe) - Delegation (object-oriented programming)

W programowania obiektowego , przekazanie dotyczy oceny człon ( właściwość lub metoda ) jednego przedmiotu (dla odbiornika) w kontekście innego oryginalnego przedmiotu (nadawcy). Delegację można wykonać jawnie, przekazując obiekt wysyłający do obiektu odbierającego, co można zrobić w dowolnym języku obiektowym ; lub niejawnie, przez reguły wyszukiwania elementów członkowskich języka, który wymaga obsługi języka dla funkcji. Delegacja niejawna jest podstawową metodą ponownego wykorzystania zachowania w programowaniu opartym na prototypach , odpowiadającą dziedziczeniu w programowaniu opartym na klasach . Najbardziej znane języki, które delegacja wsparcie na poziomie języka są Jaźni , który zawiera pojęcie delegacji przez jego pojęciu modyfikowalnych dominujących szczelin , które są stosowane na metody lookup na rozmowach samodzielne i JavaScript ; zobacz Delegacja JavaScript .

Termin delegowanie jest również używany luźno dla różnych innych relacji między obiektami; zobacz delegowanie (programowanie), aby uzyskać więcej informacji. Często mylone koncepcje to po prostu użycie innego obiektu, dokładniej określanego jako konsultacja lub agregacja ; i ocenianie elementu na jednym obiekcie przez ocenianie odpowiadającego elementu na innym obiekcie, zwłaszcza w kontekście obiektu odbierającego, co jest dokładniej określane jako przekazywanie (gdy obiekt opakowujący nie przechodzi do obiektu opakowanego). Wzór delegacja jest wzorzec projektowania oprogramowania dla realizacji delegacji, choć termin ten stosowany jest również do wglądu lub luźno spedycji.

Przegląd

To poczucie delegacji jako cechy języka programowania wykorzystującej reguły wyszukiwania metod do wysyłania tzw. autocalls zostało zdefiniowane przez Liebermana w swoim artykule z 1986 roku „Using Prototypical Objects to Implement Shared Behavior in Object-Oriented Systems”.

Delegowanie jest zależne od dynamicznego powiązania , ponieważ wymaga, aby dane wywołanie metody mogło wywoływać różne segmenty kodu w czasie wykonywania. Jest używany w całym systemie macOS (i jego poprzedniku NeXTStep ) jako sposób dostosowywania zachowania składników programu. Umożliwia implementacje, takie jak korzystanie z pojedynczej klasy dostarczonej przez system operacyjny do zarządzania oknami, ponieważ klasa przyjmuje delegata, który jest specyficzny dla programu i może w razie potrzeby zastąpić domyślne zachowanie. Na przykład, gdy użytkownik kliknie pole zamykania, menedżer okien wysyła pełnomocnikowi wywołanie windowShouldClose:, a pełnomocnik może opóźnić zamknięcie okna, jeśli istnieją niezapisane dane reprezentowane przez zawartość okna.

Delegację można scharakteryzować (i odróżnić od przekazywania ) jako późne wiązanie siebie :

... wiadomości wysłane do zmiennej self(lub this) w rodzicu "powrócą" do obiektu, który pierwotnie otrzymał wiadomość.

Oznacza to, że selfdefinicja metody w obiekcie odbierającym nie jest statycznie powiązana z tym obiektem w czasie definiowania (na przykład w czasie kompilacji lub gdy funkcja jest dołączona do obiektu), ale raczej w czasie oceny jest powiązana z oryginałem obiekt.

Argumentowano, że delegowanie może w niektórych przypadkach być preferowane od dziedziczenia, aby kod programu był bardziej czytelny i zrozumiały. Mimo że jawne delegowanie jest dość rozpowszechnione, stosunkowo niewiele głównych języków programowania implementuje delegowanie jako model alternatywny do dziedziczenia. Dokładna relacja między delegowaniem a dziedziczeniem jest skomplikowana; niektórzy autorzy uważają je za równoważne, a jeden za szczególny przypadek drugiego.

Obsługa językowa delegacji

W językach, które obsługują delegowanie za pomocą reguł wyszukiwania metod, wysyłanie metod jest definiowane w taki sposób, w jaki jest definiowane dla metod wirtualnych w dziedziczeniu: jest to zawsze najbardziej konkretna metoda wybierana podczas wyszukiwania metod. W związku z tym to oryginalna jednostka odbierająca jest początkiem wyszukiwania metody, nawet jeśli przekazała sterowanie do innego obiektu (poprzez łącze delegacji, a nie odwołanie do obiektu).

Delegowanie ma tę zaletę, że może odbywać się w czasie wykonywania i wpływać tylko na podzbiór jednostek pewnego typu, a nawet można je usunąć w czasie wykonywania. Dziedziczenie natomiast zazwyczaj dotyczy typu, a nie wystąpień i jest ograniczone do czasu kompilacji. Z drugiej strony dziedziczenie może być sprawdzane statycznie, podczas gdy delegowanie generalnie nie może bez generyków (chociaż ograniczona wersja delegowania może być statycznie bezpieczna dla typów). Delegację można nazwać „dziedziczeniem w czasie wykonywania dla określonych obiektów”.

Oto przykład pseudokodu w języku podobnym do C# / Java :

class A {
  void foo() {
    // "this" also known under the names "current", "me" and "self" in other languages
    this.bar();
  }

  void bar() {
    print("a.bar");
  }
};

class B {
  private delegate A a; // delegation link

  public B(A a) {
    this.a = a;
  }

  void foo() {
    a.foo(); // call foo() on the a-instance
  }

  void bar() {
    print("b.bar");
  }
};

a = new A();
b = new B(a); // establish delegation between two objects

Wywołanie b.foo()spowoduje wydrukowanie a.bar , ponieważ thisodnosi się do oryginalnego obiektu odbiorcy, b, w kontekście a. Wynikająca z tego niejednoznaczność thisokreślana jest mianem schizofrenii obiektowej .

Tłumacząc niejawny thisparametr jawny, wywołanie (in Bz adelegatem) a.foo()tłumaczy się na A.foo(b), przy użyciu typu arozpoznawania metody, ale obiektu delegującego bdla thisargumentu.

Używając dziedziczenia, analogiczny kod (używając wielkich liter, aby podkreślić, że rozwiązanie opiera się na klasach, a nie obiektach) to:

class A {
  void foo() {
    this.bar();
  }

  void bar() {
    print("A.bar");
  }
};

class B extends A {
  public B() {}

  void foo() {
    super.foo(); // call foo() of the superclass (A)
  }

  void bar() {
    print("B.bar");
  }
};

b = new B();

Wywołanie b.foo()spowoduje B.bar . W tym przypadku thisjest to jednoznaczne: istnieje pojedynczy obiekt b, i this.bar()rozwiązuje się do metody w podklasie.

Języki programowania ogólnie nie obsługują tej niezwykłej formy delegowania jako koncepcji języka, ale istnieje kilka wyjątków.

Podwójne dziedziczenie

Jeśli język obsługuje zarówno delegowanie, jak i dziedziczenie, można wykonać podwójne dziedziczenie , wykorzystując oba mechanizmy w tym samym czasie, co w

class C extends A {
  delegationlink D d;
}

Wymaga to dodatkowych reguł wyszukiwania metod, ponieważ istnieją teraz potencjalnie dwie metody, które można określić jako najbardziej szczegółowe (ze względu na dwie ścieżki wyszukiwania).

Powiązane obszary

Delegację można opisać jako mechanizm niskiego poziomu do udostępniania kodu i danych między jednostkami. W ten sposób buduje podstawy dla innych konstrukcji językowych. Zwłaszcza języki programowania zorientowane na role wykorzystują delegowanie, ale zwłaszcza starsze faktycznie używały agregacji , twierdząc, że używają delegacji. Nie powinno to być uważane za oszustwo, a jedynie definicje liczby mnogiej tego, co oznacza delegowanie (jak opisano powyżej).

Niedawno wykonano również prace nad dystrybucją delegacji, więc np. klienci wyszukiwarki (znajdujący tanie pokoje hotelowe) mogą korzystać ze współdzielonej encji za pomocą delegacji, aby udostępniać najlepsze hity i ogólną funkcjonalność wielokrotnego użytku.

Ernst i Lorenz w 2003 r. zasugerowali również delegację w celu uzyskania porady w zakresie programowania aspektowego .

Zobacz też

Wyróżnić:

Uwagi

Bibliografia

Zewnętrzne linki