2015-09-22 18 views
5

Giả sử tôi có 3 lớp: A, B và C. A là lớp cơ sở cho B và B là cho C. Phân cấp được giữ bình thường ở đây, nhưng đối với một phương pháp, nó phải khác nhau. Đối với lớp C nó nên hành động như nó đã được thừa hưởng từ A.Python Thừa kế từ một lớp nhưng phương thức ghi đè gọi một lớp khác?

Ví dụ như thế này:

class A(object): 
    def m(self): 
     print 'a' 

class B(A): 
    def m(self): 
     super(B, self).m() 
     print 'b' 

class C(B): 
    def m(self): 
     super(A, self).m() 
     print 'c' 

Vì vậy, về cơ bản nó sẽ làm việc như thế này:

a = A() 
a.m() 
a 

b = B() 
b.m() 
a 
b 

c = C() 
c.m() 
a 
c 

Nhưng nó sẽ không làm việc cho lớp C, bởi vì tôi gặp lỗi này:

AttributeError: 'super' object has no attribute 'm' 

Để giải quyết vấn đề này cho lớp C, tôi có thể kế thừa từ clas s A, nhưng tôi muốn kế thừa tất cả mọi thứ từ B và cho rằng phương pháp cụ thể m gọi siêu cho lớp cơ sở A. Tôi có nghĩa là phương pháp đó là một ngoại lệ. Hay tôi nên gọi nó bằng cách nào đó khác với lớp C để làm việc?

Tôi có thể làm như thế nào?

+1

bạn đã thử 'A.m (self)' thay vì sử dụng 'super'? –

+0

@MathiasEttinger không, nhưng bây giờ tôi đã thử nó và nó hoạt động hoàn hảo. Cảm ơn. Bạn có thể gửi nó như là câu trả lời, bởi vì nó giải quyết vấn đề của tôi – Andrius

+0

cho rằng để làm việc, A.m() phải là một phương pháp lớp học – fixmycode

Trả lời

4

Sử dụng cuộc gọi super, python sẽ kiểm tra số MRO của lớp học của bạn để xác định lớp nào sẽ sử dụng khi gọi chức năng bạn muốn.

Vì bạn muốn ngắn mạch hành vi này, bạn rõ ràng có thể nêu các lớp học mà bạn muốn sử dụng phương pháp này từ với:

class C(B): 
    def m(self): 
     A.m(self) 
     print 'c' 
8

Có trên thực tế hai cách để giải quyết việc này: bạn có thể tắt các gọi để super() và hoàn toàn bỏ qua các MRO như trong câu trả lời Mathias Ettinger, hoặc bạn chỉ có thể ban hành đúng cuộc gọi đến super():

class C(B): 
    def m(self): 
     super(B, self).m() 
     print 'c' 

Hãy nhớ rằng super() dự kiến ​​là đối số đầu tiên lớp mà từ đó nó sẽ bắt đầu tìm kiếm các mro. Nó thường là lớp mà trong đó cuộc gọi được thực hiện, nhưng bạn có thể vượt qua một tầng lớp trên trong mro nếu bạn muốn.

Các vấn đề liên quan