2017-04-21 1 views
1

문제를 해결하기 위해 협업 다중 상속 패턴을 사용하려고합니다.협동 다중 상속 및 파이썬 2.7 믹스

class Base1(object): 

    def __init__(self, a, b): 
     self.a = a 
     self.b = b 

    def to_tuple(self): 
     return self.a, self.b 

    def to_string(self): 
     return '%s.%s' % self.to_tuple() # (1) 

class Base2(object): 

    def __init__(self, c, d): 
     self.c = c 
     self.d = d 

    def to_tuple(self): 
     return self.c, self.d 

    def to_string(self): 
     return '%s-%s' % self.to_tuple() #(2) 

class MyMixin(Base1, Base2): 

    def __init__(self, a, b, c, d): 
     Base1.__init__(self, a, b) 
     Base2.__init__(self, c, d) 

    def to_tuple(self): 
     return Base1.to_tuple(self) + Base2.to_tuple(self) 

    def to_string(self): 
     return '{}: {} '.format(Base1.to_string(self), Base2.to_string(self)) 


mix = MyMixin('a', 'b', 'c', 'd') 
print(mix.to_string()) 

이 코드를 작성 후, 내가 기대했던 결과 : 내 파이썬 2.7 코드의 매우 단순화 된 버전은 다음과 같습니다

a.b: c-d 

하지만 코드가 실패합니다. 줄 #(1)을 실행하면 selfBase1 클래스가 아닌 MyMixin 클래스이므로 to_tuple은 4 개의 항목을 반환합니다.

나는이 문제를 해결하기 위해 찾은 유일한 방법은 #(1)#(2)와 위의 라인을 교체하는 것입니다 :

return '%s.%s' % Base1.to_tuple() # (1) 
return '%s.%s' % Base2.to_tuple() # (2) 

을 그리고 이것은 여러 가지 이유로 정말 잘못된 느낀다.

내가 뭘 잘못하고 있니?

+0

Hrm. 그 주위에는 정말 깨끗한 방법이 없습니다. 'self.to_tuple()'은 항상 오버라이드 된 메소드를 호출 할 것이다. (즉, 모든 메소드가 가상이다.) "나는 * this * 클래스의 메소드를 원한다"라고 말하는 유일한 방법은 명시 적으로 클래스의 이름을 지정하는 것이다. – dhke

+0

이 기사를 읽으려고한다. 아마도 파이썬에서 아이디어 구현을 오해했을 것입니다. http://www.artima.com/weblogs/viewpost.jsp?thread=281127 –

답변

2

다음과 같이됩니다. mix.to_string()이 호출되면 mix 인스턴스를 자체로 전달하는 Base1.to_string(self)을 호출합니다. 즉, to_string이 Base1에서 호출 될 때 MyMixin의 인스턴스를 가지며 ('a', 'b', 'c', 'd') to_tuple 전화. 그것이 실패한 이유입니다. cuz 튜플에는 4 개의 항목이 포함되어 있고 # 1 번에는 2 개의 항목 만 필요합니다.

이 문제를 해결하려면 동일한 메서드 서명을 사용하여 여러 클래스의 상속을 피하십시오. 대신 컴포지션을 사용하십시오.

class MyMixin(object): 

    def __init__(self, a, b, c, d): 
     self.base1 = Base1(a, b) 
     self.base2 = Base2(c, d) 

    def to_tuple(self): 
     return self.base1.to_tuple(self) + self.base2.to_tuple(self) 

    def to_string(self): 
     return '{}: {} '.format(self.base1.to_string(), self.base2.to_string())