2015-05-15 23 views
10

Tôi đang tạo một lớp GUI sử dụng Frame() làm lớp cơ sở của nó.Các lớp Python: Thừa kế và Instantiation

Trong phương pháp init GUIclass của tôi, tôi muốn tạo một khung phụ tùng

Ngay bây giờ tôi có:

class GUIclass(Frame): 
    def __init__(self, parent): 
     frame = Frame(self, parent) 

Nhưng tôi đã thấy điều này ở nơi khác cho dòng thứ ba:

Frame.__init__(self, parent) 

Tôi mới lập trình, python và thừa kế chắc chắn và tôi muốn biết nếu tôi hiểu sự khác biệt giữa hai chính xác. Tôi đã làm rất nhiều nghiên cứu và đọc, tôi hứa, nhưng tôi không thể tìm thấy bất cứ điều gì đã làm cho nó hoàn toàn rõ ràng:

Trong trường hợp đầu tiên tôi không gọi phương thức init như tôi đã tạo một đối tượng Frame (khung) và khi một đối tượng được tạo ra, phương thức init của nó được gọi là python.

Trong trường hợp thứ hai, người ta gọi phương thức init trên lớp (mà tôi tin là hoàn toàn hợp pháp?) Vì đối tượng Khung không được tạo, do đó sẽ không tự động làm điều đó.

Đúng không?

Tôi cũng đã nhìn thấy:

frame = Frame.__init__(self, parent) 

mà thực sự đã ném tôi ra. Đây có phải chỉ là một người làm điều gì đó dư thừa hoặc có lý do cho việc này không?

Cảm ơn sự giúp đỡ của bạn, tôi muốn thực hiện nó chậm ngay bây giờ và đảm bảo rằng tôi hiểu đầy đủ mọi dòng mã mà tôi viết thay vì viết và chạy toàn bộ chương trình mà tôi hiểu được.

+0

Bạn nên sử dụng thứ hai: 'Khung .__ init __ (bản thân, cha mẹ)' –

+2

Đầu tiên chỉ đơn giản là không chính xác như nó tạo ra một không cần thiết trong bộ khởi tạo của một đối tượng dựa trên khung. –

+0

Thứ hai và thứ ba là siêu cuộc gọi đến initializer cha trong khung, chẳng hạn như initializer của lớp con sẽ mở rộng những điều cơ bản, không ghi đè lên những điều cơ bản. Nhưng không cần phải chỉ định kết quả của cuộc gọi siêu làm cho sai thứ ba. –

Trả lời

8

Bạn nên gọi

super(GUIclass, self).__init__(parent) 

Đây là cách thích hợp để gọi số (tất cả) thừa hưởng __init__() phương pháp của bạn (s). Nó đã trong nhiều trường hợp kết quả giống hệt so với đề cập

Frame.__init__(self, parent) 

mà chỉ thiếu trừu tượng liên quan đến các mối quan hệ thừa kế và các quốc gia lớp Frame như một và chỉ một lớp mà __init__() phương pháp mà bạn có thể muốn gọi (thêm về điều này một lát sau).

cũng đề cập

frame = Frame(self.parent) 

là sai trong bối cảnh này. Nó thuộc về một mẫu khác của mối quan hệ đối tượng, cụ thể là mối quan hệ nội dung thay vì quan hệ thừa kế (mà bạn nhắm tới). Nó sẽ tạo đối tượng mới của lớp Frame thay vì khởi tạo các phần Frame của chính bạn; trong các mối quan hệ thừa kế bạn một Frame, vì vậy bạn phải khởi tạo yourself làm một cũng như khởi tạo các bộ phận chuyên dụng của bạn (được thực hiện trong phần còn lại của phương thức __init__()).Trong các mẫu quan hệ bạn chỉ đơn thuần là a Frame.

Bây giờ, sự khác biệt "nhỏ" đó tôi đã đề cập ở trên giữa việc gọi super(GUIclass, self).__init__(parent)Frame.__init__(self, parent) là gì?

Để hiểu rằng bạn cần tìm hiểu sâu hơn về các mối quan hệ thừa kế và các khả năng khác nhau của các ưu đãi này, đặc biệt là với nhiều lần kế thừa.

Xem xét một mô hình mối quan hệ hình kim cương mà trông như thế này:

  Frame 
     / \ 
    GUIclass SomeOtherClass 
      \ /
     AnotherClass 

Trong tình huống hiện tại của bạn, bạn chỉ có phía trên bên trái hai lớp, nhưng người ta không bao giờ biết những gì đang xảy đến, và bạn nên luôn luôn mã theo cách sao cho người dùng tiếp theo mã của bạn giữ tất cả các tùy chọn.

Trong mẫu hình kim cương này, bạn có AnotherClass được thừa hưởng GUIClassSomeOtherClass mà lần lượt đều thừa kế Frame.

Nếu bây giờ bạn sử dụng mô hình Frame.__init__(self, parent) trong cả GUIclassSomeOtherClass, sau đó gọi __init__() phương pháp của họ từ phương pháp __init__() của AnotherClass sẽ dẫn đến một sự kêu gọi tăng gấp đôi của __init__() phương pháp 's Frame. Điều này thường không có ý định, và để chăm sóc rằng điều này không xảy ra, cuộc gọi super đã được phát minh. Cần lưu ý rằng lệnh gọi phong nha chỉ gọi mỗi phương thức __init__() và chính xác một lần.

+0

Đối số 'siêu' sẽ theo thứ tự khác. – user2357112

+0

Cảm ơn, đã khắc phục điều đó. (Tôi không bao giờ nhớ lại những chính xác, vì vậy nếu bạn pranked tôi, tôi chỉ disimproved rằng ;-) – Alfe

+0

Ahh nó tất cả có ý nghĩa bây giờ, tôi nghĩ rằng tôi thấy sự khác biệt. Vì vậy, tôi sẽ đúng khi nói đầu tiên về mặt kỹ thuật khởi tạo một khung nhưng nó tạo ra một đối tượng khung riêng biệt hơn là nói đối tượng này có các thuộc tính khung và sau đó một số - sau đó một số là bất cứ điều gì khác là trong lớp con của tôi __init__? – Burkely91

1

Bạn sẽ phải sử dụng Frame.__init__(self, parent) như Tkinter không hỗ trợ các cuộc gọi siêu

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