2011-10-22 52 views
10

Mã này ném ngoại lệ, AttributeError, "wtf!", vì A.foo() đang gọi B.foo1(), không nên gọi số A.foo1()? Làm thế nào tôi có thể buộc nó phải gọi A.foo1() (và bất kỳ cuộc gọi phương pháp bên A.foo() nên gọi A.*)Gọi phương thức ghi đè, siêu lớp cuộc gọi đã ghi đè phương thức

class A(object): 
    def foo(self): 
     print self.foo1() 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
+1

Về cơ bản, bạn đang yêu cầu Python bỏ đi tính năng động và các phương thức ảo và * bằng cách nào đó * tìm ra để bỏ qua các phần của chuỗi tra cứu thuộc tính dựa vào vị trí mà một hàm được định nghĩa từ từ. Sẽ không xảy ra. – delnan

Trả lời

5

Nó đang làm việc như dự định, như 100% của thế giới ngôn ngữ lập trình làm việc. Lớp con ghi đè tất cả các phương thức của lớp cha.

Tuy nhiên, nếu bạn thực sự thực sự muốn gọi A.foo1() bạn có thể làm như thế này (tôi không thể đảm bảo). Và trong mọi trường hợp, bạn không được làm điều này vì điều này là chống lại tất cả các nguyên tắc lập trình tốt.

class A(object): 

    def foo(self): 
     A.foo1(self) 
2

Trong mã:

def foo2(self): 
    super(B, self).foo() 

tự là một thể hiện của B.

Khi một phương pháp có nguồn gốc từ A được gọi bằng một thể hiện của B nó sẽ bắt đầu tìm kiếm trong không gian tên từ B, và chỉ khi phương pháp này không được tìm thấy (ví dụ như không bị ghi đè bởi B) việc thực hiện từ A được sử dụng, nhưng luôn luôn tự đề cập đến B. Không có điểm tự là một thể hiện của A.

6

In loại A thay vì gọi các phương thức self bạn cần gọi A phương pháp và vượt qua theo cách thủ công self.

Đây không phải là cách làm việc bình thường - bạn cần có thực sự lý do chính đáng để thực hiện việc này như thế này.

class A(object): 
    def foo(self): 
     print A.foo1(self) 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
-1

Người ta có thể xem Python đang làm gì ở đây, nhưng cách ghi đè là cực kỳ khắc nghiệt. Lấy trường hợp khi lớp A định nghĩa 100 thuộc tính và lớp B kế thừa các thuộc tính này và thêm 1 thuộc tính nữa. Chúng ta muốn có __init __() cho B gọi __init __() cho A và để mã B chỉ xác định thuộc tính duy nhất của nó. Tương tự, nếu chúng ta định nghĩa một phương thức reset() trong A để đặt tất cả các thuộc tính về 0, thì phương thức reset() tương ứng cho B sẽ có thể gọi phương thức reset() cho A và sau đó không sử dụng thuộc tính B phải sao chép tất cả mã của A. Python đang làm khó khăn những gì được cho là một lợi thế lớn của lập trình hướng đối tượng; đó là, việc tái sử dụng mã. Tùy chọn tốt nhất ở đây là tránh ghi đè các phương thức mà chúng tôi thực sự muốn sử dụng lại. Nếu bạn muốn nhận được một cảm giác trong những biến chứng với Python đây, hãy thử mã này:

class X(object): 
    def __init__ (self): 
     print "X" 
     self.x = 'x' 
     self.reset() 
     print "back to X" 
    def reset (self): 
     print "reset X" 
     self.xx = 'xx' 

class Y(X): 
    def __init__ (self): 
     print "Y" 
     super(Y,self).__init__() 
     self.y = 'y' 
     self.reset() 
     print "back to Y" 
    def reset (self): 
     print "reset Y" 
     super(Y,self).reset() 
     print "back to reset Y" 
     self.yy = 'yy' 

aY = Y() 

(Để thực hiện công việc này đúng cách, loại bỏ các self.reset() gọi trong __init __() cho lớp Y.)

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