„Továbbítás (objektumorientált programozás)” változatai közötti eltérés

A Wikipédiából, a szabad enciklopédiából
[ellenőrzött változat][ellenőrzött változat]
Tartalom törölve Tartalom hozzáadva
B.Zsoltbot (vitalap | szerkesztései)
a replaced: <source → <syntaxhighlight (6), </source> → </syntaxhighlight> (6) AWB
fogalmak egyeztetése, linkek javítása -> már meglévő cikkre mutasson
1. sor: 1. sor:
Az [[objektumorientált programozás]]ban a '''továbbítás''' azt jelenti, hogy egy objektum egy tagjának (akár tulajdonságnak, akár egy módszernek) a használata azt eredményezi, hogy egy másik objektum megfelelő tagját használjuk valójában: egy másik objektumnak átadjuk a használatot. Az átirányítást számos tervezési mintában használják, ahol egyes tagokat egy másik objektumnak továbbítanak, míg másokat a közvetlenül használt objektum kezel. A továbbító objektumot gyakran ''wrapper objektum''nak nevezik, az explicit továbbító tagokat pedig ''wrapper funkció''nak.
Az [[objektumorientált programozás]]ban a '''továbbítás''' azt jelenti, hogy egy objektum egy tagjának (akár tulajdonságnak, akár egy metódusának) a használata azt eredményezi, hogy egy másik objektum megfelelő tagját használjuk valójában: egy másik objektumnak átadjuk a használatot. Az átirányítást számos [[Programtervezési minta|tervezési mintában]] használják, ahol egyes tagokat egy másik objektumnak továbbítanak, míg másokat a közvetlenül használt objektum kezel. A továbbító objektumot gyakran ''csomagoló objektum''nak nevezik, az explicit továbbító tagokat pedig ''csomagoló funkció''nak.


== Delegálás ==
== Delegálás ==
A továbbítást gyakran összekeverik a delegálással; formálisan ezek kiegészítő fogalmak. Mindkét esetben két objektum létezik, és az első (küldő, csomagoló) objektum a második (fogadó, csomagolandó) objektumot használja, például egy metódus meghívására. Különböznek abban, hogy mi utal önmagára a fogadó objektumra (formálisan a metódus kiértékelési környezetében a fogadó objektumra): átruházáskor a küldő objektumra, míg továbbításkor a fogadó obejktumra utal. Vegyük figyelembe, hogy a "self" kulcsszó gyakran implicit módon van használva a dinamikus továbbítás részeként (módszer felbontása: melyik funkcióra utal a módszer neve).
A továbbítást gyakran összekeverik a delegálással; formálisan ezek kiegészítő fogalmak. Mindkét esetben két objektum létezik, és az első (küldő, csomagoló) objektum a második (fogadó, csomagolandó) objektumot használja, például egy metódus meghívására. Különböznek abban, hogy mi utal önmagára a fogadó objektumra (formálisan a metódus kiértékelési környezetében a fogadó objektumra): átruházáskor a küldő objektumra, míg továbbításkor a fogadó obejktumra utal. Vegyük figyelembe, hogy a "self" kulcsszó gyakran implicit módon van használva a dinamikus továbbítás részeként (metódus felbontása: melyik funkcióra utal a metódus neve).


{{quote|A továbbítás és a delegálás közötti különbség a saját paraméterek összekötésében van, amikor a csomagolandót a csomagolón keresztül hívják meg. Delegálással a saját paraméter a csomagolóhoz van kötve, továbbításnál pedig a csomagolandóhoz. A továbbítás az automatikus üzenetküldés egy formája; a delegálás az öröklés egy formája, amelyben a szülő (szuperosztály) összekötése futási időben történik, nem pedig az összeállítási/összekapcsolási időben, mint a „normál” öröklésnél.<ref name="buechiweck">{{cite book |first1=Martin |last1=Büchi |first2=Wolfgang |last2=Weck |title=ECOOP 2000 — Object-Oriented Programming
{{quote|A továbbítás és a delegálás közötti különbség a saját paraméterek összekötésében van, amikor a csomagolandót a csomagolón keresztül hívják meg. Delegálással a saját paraméter a csomagolóhoz van kötve, továbbításnál pedig a csomagolandóhoz. A továbbítás az automatikus üzenetküldés egy formája; a delegálás az öröklés egy formája, amelyben a szülő (ősosztály) összekötése futási időben történik, nem pedig az összeállítási/összekapcsolási időben, mint a „normál” öröklésnél.<ref name="buechiweck">{{cite book |first1=Martin |last1=Büchi |first2=Wolfgang |last2=Weck |title=ECOOP 2000 — Object-Oriented Programming
|chapter=Generic Wrappers |chapter-url=http://www.lirmm.fr/~ducour/Doc-objets/ECOOP/papers/1850/18500201.pdf |volume=1850 |series=Lecture Notes in Computer Science |year=2000 |doi=10.1007/3-540-45102-1_10 |pages=[https://books.google.com/books?id=CFtuCQAAQBAJ&pg=PA212&dq=forwarding+vs.+delegation 212–213]|isbn=978-3-540-67660-7 }}</ref>
|chapter=Generic Wrappers |chapter-url=http://www.lirmm.fr/~ducour/Doc-objets/ECOOP/papers/1850/18500201.pdf |volume=1850 |series=Lecture Notes in Computer Science |year=2000 |doi=10.1007/3-540-45102-1_10 |pages=[https://books.google.com/books?id=CFtuCQAAQBAJ&pg=PA212&dq=forwarding+vs.+delegation 212–213]|isbn=978-3-540-67660-7 }}</ref>
}}
}}
26. sor: 26. sor:
delegáláskor ez m2 és n1 kimenetet eredményez, mivel az <code>n()</code>értékét az eredeti (küldõ) objektummal összefüggésben értékeli ki, míg a továbbítás alatt ez m2, n2 kimenetet eredményez mert <code>n()</code> a fogadó objektummal összefüggésben van kiértékelve.<ref name="buechiweck" />
delegáláskor ez m2 és n1 kimenetet eredményez, mivel az <code>n()</code>értékét az eredeti (küldõ) objektummal összefüggésben értékeli ki, míg a továbbítás alatt ez m2, n2 kimenetet eredményez mert <code>n()</code> a fogadó objektummal összefüggésben van kiértékelve.<ref name="buechiweck" />


Általános használat esetén a továbbítást gyakran "delegálásnak" nevezik, vagy átruházásnak tekintik, ám gondos használat esetén egyértelműen megkülönböztető, hogy a "self" mire utal. Míg a delegálás hasonlít az örökléshez, lehetővé téve a működésen alapuló újrafelhasználást (és konkrétan a kód újrafelhasználását) anélkül, hogy megváltoztatná a környezetét. A továbbítás hasonló a kompozícióval, mivel a végrehajtás csak a fogadó objektumtól függ, és nem az (eredeti) küldõ objektumtól. Mindkét esetben az újrafelhasználás dinamikus, vagyis futási időben meghatározott (az objektum alapján, amelyre a felhasználást átruházják vagy továbbítja), nem pedig statikus, azaz a fordítási időben meghatározott (az az osztály alapján, amelytől örökölt). Az örökléshez hasonlóan a delegálás lehetővé teszi a küldő objektum számára az eredeti viselkedés módosítását, de érzékeny a alaposztályhoz hasonló problémákra. A továbbítás erősebb beágyazást biztosít és elkerüli ezeket a problémákat, lásd az objektum-összetételt az öröklés felett.<ref name="buechiweck" />
Általános használat esetén a továbbítást gyakran "delegálásnak" nevezik, vagy átruházásnak tekintik, ám gondos használat esetén egyértelműen megkülönböztető, hogy a "self" mire utal. Míg a delegálás hasonlít az örökléshez, lehetővé téve a működésen alapuló újrafelhasználást (és konkrétan a kód újrafelhasználását) anélkül, hogy megváltoztatná a környezetét. A továbbítás hasonló a kompozícióhoz, mivel a végrehajtás csak a fogadó objektumtól függ, és nem az (eredeti) küldõ objektumtól. Mindkét esetben az újrafelhasználás dinamikus, vagyis futási időben meghatározott (az objektum alapján, amelyre a felhasználást átruházják vagy továbbítja), nem pedig statikus, azaz a fordítási időben meghatározott (az az osztály alapján, amelytől örökölt). Az örökléshez hasonlóan a delegálás lehetővé teszi a küldő objektum számára az eredeti viselkedés módosítását, de érzékeny a alaposztályhoz hasonló problémákra. A továbbítás erősebb beágyazást biztosít és elkerüli ezeket a problémákat, lásd az objektum-összetételt az öröklés felett.<ref name="buechiweck" />


== Példák ==
== Példák ==
117. sor: 117. sor:
=== Komplex ===
=== Komplex ===


A bonyolultabb eset a díszítő minta, amely interfészek használatával rugalmasabbá és típusbiztonságosabbá teszi a továbbítást. A "rugalmasság" itt azt jelenti, hogy a C-nek semmilyen módon nem kell utalnia A-ra vagy B-re, mivel a továbbítás váltása C-ből származik. Ebben a példában a C osztály továbbíthat minden osztályhoz, amely implementálja az I interfészt. A C osztály rendelkezik egy metódussal, hogy tudjon váltani a továbbítók között. Az implements kulcsszó javítva a típusbiztonságot, mivel minden osztálynak implementálnia kell a metódusokat amelyeket az interfész tartalmaz. A fő kompromisszum az több kódot jelent.
A bonyolultabb eset a [[Díszítő programtervezési minta|díszítő minta]], amely interfészek használatával rugalmasabbá és típusbiztonságosabbá teszi a továbbítást. A "rugalmasság" itt azt jelenti, hogy a C-nek semmilyen módon nem kell utalnia A-ra vagy B-re, mivel a továbbítás váltása C-ből származik. Ebben a példában a C osztály továbbíthat minden osztályhoz, amely implementálja az I interfészt. A C osztály rendelkezik egy metódussal, hogy tudjon váltani a továbbítók között. Az implements kulcsszó javítva a típusbiztonságot, mivel minden osztálynak implementálnia kell a metódusokat amelyeket az interfész tartalmaz. A fő kompromisszum az több kódot jelent.


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
162. sor: 162. sor:
A továbbítást számos tervezési mintában használják.<ref>{{cite book |last=Gamma |first=Erich |authorlink=Erich Gamma |title=Design Patterns: Elements of Reusable Object-Oriented Software |year=1995 |publisher=[[Addison-Wesley]] |isbn=978-0-201-63361-0 |authorlink3=Ralph Johnson (computer scientist) |authorlink2=Richard Helm |first2=Richard |last2=Helm |authorlink4=John Vlissides |first3=Ralph |last3=Johnson |first4=John |last4=Vlissides |title-link=Design Patterns (book) |bibcode=1995dper.book.....G}}</ref> A továbbítást közvetlenül több mintában használják:
A továbbítást számos tervezési mintában használják.<ref>{{cite book |last=Gamma |first=Erich |authorlink=Erich Gamma |title=Design Patterns: Elements of Reusable Object-Oriented Software |year=1995 |publisher=[[Addison-Wesley]] |isbn=978-0-201-63361-0 |authorlink3=Ralph Johnson (computer scientist) |authorlink2=Richard Helm |first2=Richard |last2=Helm |authorlink4=John Vlissides |first3=Ralph |last3=Johnson |first4=John |last4=Vlissides |title-link=Design Patterns (book) |bibcode=1995dper.book.....G}}</ref> A továbbítást közvetlenül több mintában használják:


* [[Felelősséglánc programtervezési minta|Felelősséglánc minta]]
* Chain-of-responsibility pattern
* Decorator pattern: A díszítő objektum hozzáadja saját tagjait, majd továbbadja a díszített tárgyat.
* [[Díszítő programtervezési minta|Díszítő/dekorátr minta]]: A díszítő objektum hozzáadja saját tagjait, majd továbbadja a díszített tárgyat.
* [[Helyettes programtervezési minta|Helyettesítő/proxy minta]]
* Proxy pattern


A továbbítás más mintákban is felhasználható, de a felhasználás gyakran módosul, például egy metódushívás egy objektumra több különféle metódus hívását eredményezi egy másikon:
A továbbítás más mintákban is felhasználható, de a felhasználás gyakran módosul, például egy metódushívás egy objektumra több különféle metódus hívását eredményezi egy másikon:


* [[Illesztő programtervezési minta|Illesztő/Adapter minta]]
* Adapter pattern
* [[Híd programtervezési minta| Híd minta]]
* Bridge pattern
* [[Homlokzat programtervezési minta|Homlokzat/Facade minta]]
* Facade pattern


== Források ==
== Források ==

A lap 2020. október 21., 11:19-kori változata

Az objektumorientált programozásban a továbbítás azt jelenti, hogy egy objektum egy tagjának (akár tulajdonságnak, akár egy metódusának) a használata azt eredményezi, hogy egy másik objektum megfelelő tagját használjuk valójában: egy másik objektumnak átadjuk a használatot. Az átirányítást számos tervezési mintában használják, ahol egyes tagokat egy másik objektumnak továbbítanak, míg másokat a közvetlenül használt objektum kezel. A továbbító objektumot gyakran csomagoló objektumnak nevezik, az explicit továbbító tagokat pedig csomagoló funkciónak.

Delegálás

A továbbítást gyakran összekeverik a delegálással; formálisan ezek kiegészítő fogalmak. Mindkét esetben két objektum létezik, és az első (küldő, csomagoló) objektum a második (fogadó, csomagolandó) objektumot használja, például egy metódus meghívására. Különböznek abban, hogy mi utal önmagára a fogadó objektumra (formálisan a metódus kiértékelési környezetében a fogadó objektumra): átruházáskor a küldő objektumra, míg továbbításkor a fogadó obejktumra utal. Vegyük figyelembe, hogy a "self" kulcsszó gyakran implicit módon van használva a dinamikus továbbítás részeként (metódus felbontása: melyik funkcióra utal a metódus neve).

„A továbbítás és a delegálás közötti különbség a saját paraméterek összekötésében van, amikor a csomagolandót a csomagolón keresztül hívják meg. Delegálással a saját paraméter a csomagolóhoz van kötve, továbbításnál pedig a csomagolandóhoz. A továbbítás az automatikus üzenetküldés egy formája; a delegálás az öröklés egy formája, amelyben a szülő (ősosztály) összekötése futási időben történik, nem pedig az összeállítási/összekapcsolási időben, mint a „normál” öröklésnél.[1]

Például, adott a következő kód:

// Sender
void n() {
  print("n1");
}

// Receiver
void m() {
  print("m2, "); n();
}

void n() {
  print("n2");
}

delegáláskor ez m2 és n1 kimenetet eredményez, mivel az n()értékét az eredeti (küldõ) objektummal összefüggésben értékeli ki, míg a továbbítás alatt ez m2, n2 kimenetet eredményez mert n() a fogadó objektummal összefüggésben van kiértékelve.[1]

Általános használat esetén a továbbítást gyakran "delegálásnak" nevezik, vagy átruházásnak tekintik, ám gondos használat esetén egyértelműen megkülönböztető, hogy a "self" mire utal. Míg a delegálás hasonlít az örökléshez, lehetővé téve a működésen alapuló újrafelhasználást (és konkrétan a kód újrafelhasználását) anélkül, hogy megváltoztatná a környezetét. A továbbítás hasonló a kompozícióhoz, mivel a végrehajtás csak a fogadó objektumtól függ, és nem az (eredeti) küldõ objektumtól. Mindkét esetben az újrafelhasználás dinamikus, vagyis futási időben meghatározott (az objektum alapján, amelyre a felhasználást átruházják vagy továbbítja), nem pedig statikus, azaz a fordítási időben meghatározott (az az osztály alapján, amelytől örökölt). Az örökléshez hasonlóan a delegálás lehetővé teszi a küldő objektum számára az eredeti viselkedés módosítását, de érzékeny a alaposztályhoz hasonló problémákra. A továbbítás erősebb beágyazást biztosít és elkerüli ezeket a problémákat, lásd az objektum-összetételt az öröklés felett.[1]

Példák

Az explicit továbbítás egyszerű példája Java-ban: a Bpéldány továbbítja a hívásokat a foo metódus a mezőjének:

class B {
    A a;
    T foo() { return a.foo(); }
}

Vegyük figyelembe, hogy az a.foo() végrehajtásakor a this objektum egy a (A altípusa), nem pedig az eredeti objektum (B példánya). Ezenkívül a -nak nem feltétlenül kell az A példányának lennie: lehet egy altípus példánya is. Valójában, A -nak nem is kell osztálynak lennie: lehet interfész.

Az örökléssel ellentétben, amelyben a fooértéket egy A szuperosztályban definiálják (amelynek osztálynak kell lennie, nem interfésznek), és amikorB, alosztály példányára hívják, akkor az A-ban definiált kódot használja, de ez az objektum még mindig B példánya:

class A {
    T foo() { /* ... */ };
}

class B extends A {
}

Ebben a Python-példában a B osztály továbbítja a foo metódustés az x property-t az a mezőben lévő objektumnak: ezek használata b-n (B példánya) ugyanaz, mint a b.a használata (A példánya, amelyhez ezek vannak továbbítva).

class A(object):
    def __init__(self, x) -> None:
        self.x = x

    def foo(self):
        print(self.x)

class B(object):
    def __init__(self, a) -> None:
        self.a = a

    def foo(self):
        self.a.foo()

    @property
    def x(self):
        return self.a.x

    @x.setter
    def x(self, x):
        self.a.x = x

    @x.deleter
    def x(self):
        del self.a.x

a = A(42)
b = B(a)
b.foo()  # Prints '42'.
b.x  # Has value '42'
b.x = 17   # b.a.x now has value 17
del b.x  # Deletes b.a.x.

Szimpla

Ebben a Java-példában a Printer osztálynak van print metódusa. Ez a print metódus ahelyett, hogy maga végrehajtaná a kiíratást, a RealPrinter osztályú objektumnak továbbítja ezt. A külvilág számára úgy tűnik, hogy a Printer objektum végzi a kiíratást, de a RealPrinter objektum az, amely valójában a munkát végzi.

Az átirányítás egyszerűen valamilyen kötelességet ruház át valaki másra. Íme egy egyszerű példa:

class RealPrinter { // the "receiver"
    void print() { 
        System.out.println("Hello world!"); 
    }
}

class Printer { // the "sender"
    RealPrinter p = new RealPrinter(); // create the receiver
    void print() {
        p.print(); // calls the receiver
    }
}
 
public class Main {
    public static void main(String[] arguments) {
        // to the outside world it looks like Printer actually prints.
        Printer printer = new Printer();
        printer.print();
    }
}

Komplex

A bonyolultabb eset a díszítő minta, amely interfészek használatával rugalmasabbá és típusbiztonságosabbá teszi a továbbítást. A "rugalmasság" itt azt jelenti, hogy a C-nek semmilyen módon nem kell utalnia A-ra vagy B-re, mivel a továbbítás váltása C-ből származik. Ebben a példában a C osztály továbbíthat minden osztályhoz, amely implementálja az I interfészt. A C osztály rendelkezik egy metódussal, hogy tudjon váltani a továbbítók között. Az implements kulcsszó javítva a típusbiztonságot, mivel minden osztálynak implementálnia kell a metódusokat amelyeket az interfész tartalmaz. A fő kompromisszum az több kódot jelent.

interface I {
	void f();
	void g();
}
 
class A implements I {
	public void f() { System.out.println("A: doing f()"); }
	public void g() { System.out.println("A: doing g()"); }
}
 
class B implements I {
	public void f() { System.out.println("B: doing f()"); }
	public void g() { System.out.println("B: doing g()"); }
}
 
// changing the implementing object in run-time (normally done in compile time)
class C implements I {
	I i = null;
	// forwarding
	public C(I i){ setI(i); }
	public void f() { i.f(); }
	public void g() { i.g(); }
 
	// normal attributes
	public void setI(I i) { this.i = i; }
}
 
public class Main {
	public static void main(String[] arguments) {
		C c = new C(new A());
		c.f();	// output: A: doing f()
		c.g();	// output: A: doing g()
		c.setI(new B());
		c.f();	// output: B: doing f()
		c.g();	// output: B: doing g()
	}
}

Alkalmazások

A továbbítást számos tervezési mintában használják.[2] A továbbítást közvetlenül több mintában használják:

A továbbítás más mintákban is felhasználható, de a felhasználás gyakran módosul, például egy metódushívás egy objektumra több különféle metódus hívását eredményezi egy másikon:

Források

  1. a b c Generic Wrappers, ECOOP 2000 — Object-Oriented Programming, Lecture Notes in Computer Science, 212–213. o.. DOI: 10.1007/3-540-45102-1_10 (2000). ISBN 978-3-540-67660-7 
  2. Gamma, Erich. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley (1995). ISBN 978-0-201-63361-0 

Fordítás

  • Ez a szócikk részben vagy egészben a Forwarding (object-oriented programming) című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.