2012-01-04 16 views
7

Tôi có một mô hình sau và lớp cơ sở trừu tượngMột mô hình django rằng lớp con một abc, cung cấp cho một cuộc xung đột metaclass

import abc 
from django.db import models 


class AbstractBase(): 
    __metaclass__ = abc.ABCMeta 

    @abc.abstractmethod 
    def my_method(self): 
     return 


class MyModel(models.Model, AbstractBase): 
    @abc.abstractmethod 
    def my_method(self): 
     return 1 

Nhưng tôi nhận được lỗi sau.

xung đột metaclass: các metaclass của một lớp được thừa kế phải là một (không nghiêm ngặt) lớp con của các metaclasses của tất cả các căn cứ của nó

Tôi nghĩ vấn đề ở đây là (Vì nó được mô tả ở đây http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/) rằng hai lớp cơ sở có hai metaclasses khác nhau nên python không thể quyết định metaclass nào dùng cho đối tượng con.

Để giải quyết việc này tôi loại bỏ nhiều thừa kế và sử dụng theo phương pháp đăng ký để đăng ký lớp con

abc.register(Child) 

Nhưng tôi không thực sự thích phương pháp này vì nó trông giống như khỉ vá.

Có cách nào khác để giải quyết vấn đề này không?

Tôi cố gắng gán mô hình Metaclass cho Trẻ em một cách rõ ràng nhưng nó không hoạt động. Tôi không tìm cách giải quyết nó bằng cách viết mã. Tôi nghĩ rằng điều này phải được giải quyết bằng cách thay đổi cấu trúc lớp học của tôi.

+0

Tôi nghĩ rằng bạn sẽ phải tạo một metaclass mới mà cả hai điều của django và abc, có thể bằng cách gọi metaclasses tương ứng của họ theo thứ tự, có thể sử dụng thừa kế. – cha0site

+0

Không có gì đáng ngờ khi sử dụng phương pháp abs.register - nó được thiết kế chính xác cho những trường hợp này. BTW, Python cách o f suy nghĩ mọi thứ được thực hiện vì vậy bạn hiếm khi nên _need_ giao diện và như vậy - có thể bạn đang quá hạn chế bởi cách mọi thứ được thực hiện bằng ngôn ngữ tĩnh? – jsbueno

+0

@jsbueno - Bạn có thể đúng, nhưng tôi sẽ cần phải thực hiện chức năng giao diện theo một cách nào đó. Đây là một ví dụ cấy - https://gist.github.com/1559689. Có cách nào tốt hơn để thực hiện chức năng này, trong python? – yilmazhuseyin

Trả lời

2

Ngoài việc tạo ra một metaclass mới được thừa kế từ cả ABCMetaModelBase, hoặc làm ABCMeta kế thừa từ ModelBase, không có nhiều bạn có thể làm.

Tuy nhiên, có thể mẫu đăng ký khác có thể phù hợp? Có thể một cái gì đó như contrib.admin.autodiscover? Hoặc một trang trí lớp học? Hoặc một vòng lặp ở cuối tệp .py gọi register trên các lớp thích hợp (ví dụ: for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var))?

Chỉnh sửa: D'oh. Tôi giả định rằng ABCMeta là một ví dụ, không phải là ABCMeta. Đó là những gì tôi nhận được để duyệt StackOverflow khi ngủ quá ít.

+0

Kết luận của tôi về điều này là nếu tôi đang sử dụng abc như một giao diện, tôi nên sử dụng abc.register. Tôi thực sự nghĩ rằng cần có một cách tốt hơn để thực hiện một giao diện (http://www.python.org/dev/peps/pep-0245/). Nếu không có chúng, các tính năng của python có vẻ rất yếu đối với tôi. – yilmazhuseyin

+3

Nếu bạn cảm thấy rằng "làm cho OO của Python yếu", thì tôi có thể cho rằng sự hiểu biết của bạn về "yêu cầu đối với OO mạnh" khác với các nhà thiết kế của Python (hoặc bạn vô tình gõ "oo" khi bạn muốn gõ "kiểm tra kiểu tĩnh"?) –