2011-08-09 15 views
6

Tak więc piszę kod i ostatnio spotkałem się z koniecznością zaimplementowania kilku miksów. Moje pytanie brzmi, jaki jest właściwy sposób zaprojektowania miksu? Użyję przykładowego kodu poniżej, aby zilustrować moje dokładne zapytanie.Python Standardy MixIn

class Projectile(Movable, Rotatable, Bounded): 
    '''A projectile.''' 
    def __init__(self, bounds, position=(0, 0), heading=0.0): 
     Movable.__init__(self) 
     Rotatable.__init__(self, heading) 
     Bounded.__init__(self, bounds) 
     self.position = Vector(position) 

    def update(self, dt=1.0): 
     '''Update the state of the object.''' 
     scalar = self.velocity 
     heading = math.radians(self.heading) 
     direction = Vector([math.sin(heading), math.cos(heading)]) 
     self.position += scalar * dt * direction 
     Bounded.update(self) 

class Bounded(object): 
    '''A mix-in for bounded objects.''' 
    def __init__(self, bounds): 
     self.bounds = bounds 

    def update(self): 
     if not self.bounds.contains(self.rect): 
      while self.rect.top > self.bounds.top: 
       self.rect.centery += 1 
      while self.rect.bottom < self.bounds.bottom: 
       self.rect.centery += 1 
      while self.rect.left < self.bounds.left: 
       self.rect.centerx += 1 
      while self.rect.right > self.bounds.right: 
       self.rect.centerx -= 1 

Zasadniczo, zastanawiam się, czy mix-ins coś w rodzaju interfejsów Java, gdzie nie jest obecny (w przypadku ukryte Pythona) umowie, że jeśli chce się użyć kodu trzeba zdefiniować pewne zmienne/funkcje (w przeciwieństwie do frameworka), czy jest to bardziej jak kod, który napisałem powyżej, gdzie każde miksowanie musi zostać zainicjowane jawnie?

+0

Nie wiem, że jest to reguła, ale w języku Python nietypowe jest nieliniowe '__init__'. Chciałbym ograniczyć jedną klasę podstawową, "prawdziwego" rodzica, do posiadania i metodę "__init__". Ponadto, jak pisze twój przykład, nigdy nie wywołujesz 'Bounded.update()'. – agf

+0

Tak, napisałem przykład trochę zbyt szybko. Co się tyczy twojej uwagi na temat __init__, czy jednak sugeruje to, że mix-ins nie powinno się łączyć z __init__ (w takim przypadku pochodzą one z umowami)? –

+0

Naprawdę nie wiem o "nie powinienem" - ale w Pythonie to z pewnością sposób, w jaki bym to zrobił. Nie napisałem tego jako odpowiedzi, ponieważ była to opinia. Nie jestem pewien, czy dostaniesz odpowiedź na to, że nie jest to opinia (ta poniżej jest po prostu nie na temat), więc daj mi znać, jeśli chcesz to opublikować jako odpowiedź. – agf

Odpowiedz

2

Możesz mieć oba zachowania w Pythonie. Możesz wymusić reimplementację używając abstrakcyjnych klas bazowych lub podnosząc NotImplementedError w funkcjach wirtualnych.

Jeśli init są ważne w klasach rodzica, musisz je wywołać. Jak powiedział eryksun, użyj wbudowanej funkcji super, aby wywołać inicjatory rodzica (w ten sposób inicjalizator dla danej klasy zostanie wywołany tylko raz).

Wniosek: zależy od tego, co masz. W twoim przypadku musisz zadzwonić pod numer init i powinieneś użyć super.