2016-03-19 22 views
0

Ich habe eine Klasse A, die Klasse B im strengen Sinne einer "hat-a" -Beziehung Ie enthält. Es macht Sinn, dass A B enthält. Allerdings gibt es nur ein paar spezifische Methoden, die B betreffen. Ein Großteil der Modellierung wird dazu führen, dass Klasse A eine Methode hat, die Methoden der Klasse B ohne wirklichen Nutzen aufruft der Nachteil von zwei Funktionsaufrufen.Zusammensetzung OOP

class A(): 

    b=B() 

    __init__(self): 
     self.a=[] 

    def addToA(self,a): 
     self.a.append(a) 

    def addToB(a): 
     # do something with self.a 
     b.addToB(a) 

Was sind die Gedanken der Menschen auf Methoden innerhalb einer Bereitstellung, die speziell erforderlich ist, wenn es ändert B. gehen jedoch direkt sonst B:

z=A() 
z.addToB(a) 
z.b.methSpecificToB(x,y,z) 

Ich glaube, ich bin ich breche die Verkapselung Ein wenig tut dies jedoch mehr Sinn als einfach überflüssige Methoden zur Verfügung stellen.

+0

Sollen "b" 'self.b' und' addToB() '' self' als erstes Agument sein? –

+0

Hallo Martin, b sollte ein Klassenattribut sein und sollte unter allen Instanzen geteilt werden. Ich habe diesen Code im realen Code über vereinfacht vereinfacht. Klasse B ist eigentlich eine Bibliothek für eine Datenbank ... –

Antwort

1

Ich würde im Allgemeinen bevorzugen die Indirection des Aufrufs der Methode auf A, um die Methode auf B aufzurufen, weil es A-Clients vor Änderungen in der Implementierung schützt von A und B. Zum Beispiel Wenn spätere Änderungen erfordern, dass methodSpecificToB und einige andere Methoden auf B aufgerufen werden, muss ich nur A.addtoB ändern, während, wenn Z und andere Klassen B direkt aufrufen, sie alle geändert werden müssen.

Letztlich hängt es von der Wahrscheinlichkeit ab, dass B sich ändert. Wenn das nie passieren wird, ist das Aussetzen von B wahrscheinlich in Ordnung, aber wenn es möglich ist, ist die Indirektion sicherer.

+0

Danke Snakecharmer ja das macht Sinn. Ich habe mich darauf gelehnt. –

0

Ich würde dies mit einem Dekorateur lösen. Wenn Sie A.B festlegen, wird automatisch B.A festgelegt.

class A: 

    _b = None 

    @property 
    def b(self): 
     return self._b 

    @b.setter 
    def b(self, b): 
     self._b = b 
     b.a = self 

class B: 

    a = None 

foo = A() 
bar = B() 
foo.b = bar 
bar.a == foo # True 
foo.b == bar # True 

Was hier passiert, ist, dass, wenn Sie foo.b gesetzt, als foo._b gespeichert wird. (Der Unterstrich weist auf eine "versteckte" Variable hin, die normalerweise für die interne Verwendung verwendet wird.) Gleichzeitig wird bar.a auf foo gesetzt, sodass Sie von foo aus bar zugreifen können.

Beim Versuch, auf foo.b zuzugreifen, wird stattdessen foo._b zurückgegeben. Da wir dies früher auf bar setzen, greifen wir auch auf bar von foo zu.

Es gibt viele Tutorials zu den Python-Eigenschaften. This one ist nett, okay.