2010-05-23 32 views
9

lần đầu tiên khi tràn ngăn xếp.Trong Ruby hoặc Python, khái niệm về lớp học có thể được viết lại không?

Tôi đang xem xét sử dụng một số tính năng lập trình meta được cung cấp bởi Ruby hoặc Python, nhưng trước tiên tôi cần biết mức độ mà chúng sẽ cho phép tôi mở rộng ngôn ngữ. Điều chính tôi cần làm là viết lại khái niệm Lớp. Điều này không có nghĩa là tôi muốn viết lại một lớp cụ thể trong thời gian chạy, mà đúng hơn là tôi muốn tạo khái niệm của riêng mình về những gì một lớp Lớp là. Để trở thành một cái lò cụ thể hơn ở đây, tôi muốn tạo một cái gì đó là như những gì mọi người thường gọi là Lớp, nhưng tôi muốn tuân theo một giả định "open world". Trong "thế giới khép kín" của các lớp bình thường, nếu tôi tuyên bố Poodle là một lớp con của Dog là một lớp con của Animal, thì tôi biết rằng Poodle cũng không phải là một kiểu FurCoat. Tuy nhiên, trong một Class thế giới mở, thì đối tượng Poodle mà tôi đã định nghĩa có thể hoặc không thể và đối tượng của kiểu FurCoat và chúng tôi sẽ không biết chắc chắn cho đến khi tôi giải thích rằng tôi có thể mặc poodle. (Poodle nghèo.) Tất cả điều này đã làm với một nghiên cứu tôi đang làm liên quan đến ontology OWL.

Để bạn biết, tôi đã cố gắng tìm thông tin trực tuyến, nhưng do quá tải các điều khoản ở đây, tôi không tìm thấy bất kỳ điều gì hữu ích.

Siêu cảm ơn, John

UPDATE: Tôi chỉ nghĩ đến một trường hợp sử dụng tốt cho khái niệm mở thế giới của tôi về Class. Có lẽ điều này sẽ cung cấp một sự hiểu biết tốt hơn về những gì tôi thực sự muốn làm. Tôi muốn có thể "mô tả" một Lớp hơn là xác định nó. Ví dụ, tôi muốn có thể nói rằng một con chó là bất cứ điều gì mà a) có bốn chân b) barks. Sau đó, tôi muốn để có thể tạo ra một đối tượng của lớp không xác định, và mô tả rằng đối tượng này có bốn chân. Tại thời điểm này đối tượng vẫn là loại không xác định. Sau đó, tôi muốn nói rằng đối tượng sủa. Tại thời điểm này, đối tượng sẽ được biết đến là (có thể trong số những thứ khác) một con chó.

+2

Có thể đó là nhiều thừa kế mà bạn đang theo dõi? Điều đó sẽ cho phép 'Poodle' là một lớp con của cả hai' Dog' và 'FurCoat', và kết quả là, phát hiện rằng' Poodle' là một phân lớp của 'Dog' không loại trừ khả năng nó là một lớp con của' FurCoat'. –

+1

Có vẻ như bạn đã quá cố định về ý tưởng sửa đổi lớp học này. Thay đổi cách 'is_a?' Hoạt động trong Ruby để so sánh các trường thay vì các kiểu lớp là có thể và nên làm những gì bạn muốn. –

Trả lời

7

Tôi đồng ý với Samir rằng nó có vẻ giống như gõ vịt. Bạn không cần phải quan tâm đến 'loại' một đối tượng thực sự 'là' bạn chỉ cần bận tâm với những gì một đối tượng có thể 'làm'. Điều này đúng trong cả Ruby và Python.

Tuy nhiên, nếu bạn thực sự đang kiểm tra các loại lớp học và bạn thực sự cần phải có một đối tượng Poodle tùy chọn cũng là một FurCoat lúc chạy, sau đó là cách để làm điều này trong Ruby là mixin một module FurCoat vào đối tượng Poodle như sau:

class Poodle; end 
module FurCoat; def wear; end; end 

my_poodle = Poodle.new 
my_poodle.is_a?(Poodle) #=> true 
my_poodle.is_a?(FurCoat) #=> false 
my_poodle.wear #=> NoMethodError 

# now we mix in the FurCoat module 
my_poodle.extend(FurCoat) 

# my_poodle is now also a FurCoat 
my_poodle.is_a?(Poodle) #=> true (still) 
my_poodle.is_a?(FurCoat) #=> true 
my_poodle.wear #=> the wear method now works 

EDIT (do cho câu hỏi cập nhật của bạn):

bạn vẫn không cần phải viết lại Class để đạt được những gì bạn muốn, bạn chỉ cần ne ed để khỉ vá các phương thức kind_of?is_a? (và có khả năng instance_of?) trên mô-đun Kernel của Ruby. Kể từ Ruby có lớp mở này có thể dễ dàng thực hiện:

class Module 
    def obj_implements_interface?(obj) 
     false 
    end 
end 

module Kernel 
    alias_method :orig_is_a?, :is_a? 

    def is_a?(klass) 
     orig_is_a?(klass) || klass.obj_implements_interface?(self) 
    end 
end 

Và sau đó xác định cho mỗi lớp học (hoặc mô-đun) ý nghĩa của nó cho một đối tượng để thực hiện giao diện của nó:

class Dog 
    def self.obj_implements_interface?(obj) 
     obj.respond_to?(:bark) && obj.respond_to?(:num_legs) && obj.num_legs == 4 
    end 
end 

module FurCoat 
    def self.obj_implements_interface?(obj) 
     obj.respond_to?(:wear) 
    end 
end 

Bây giờ kiểm tra nó:

my_poodle = Poodle.new 
my_poodle.is_a?(FurCoat) #=> false 

# now define a wear method on my_poodle 
def my_poodle.wear; end 
my_poodle.is_a?(FurCoat) #=> true 
+0

Điều đầu tiên đầu tiên, tôi rất ấn tượng với stackOverflow và với các bạn. Tôi đi để có được một vết cắn và tôi trở lại và tôi có 63 lượt xem và một số câu trả lời khá dễ hiểu để khởi động! Vì vậy, Samir và lan can, các bạn đang nhận được * gần gũi hơn * với chức năng tôi cần, nhưng tôi không nghĩ rằng bạn có thể làm cho nó tất cả các cách đó. Tôi không thể gõ vịt vì nếu nó có thể bay, nó không nhất thiết là một chiếc máy bay. Loại thực tế là quan trọng, nó chỉ là không biết đến.Tôi không thể làm mixin vì đôi khi tôi sẽ cần * suy luận * rằng nó cũng là một FurCoat mà không chỉ định như vậy. Tôi thực sự cần để có thể viết lại Class – JnBrymn

+0

Rất hay. Điều đó thực sự khiến tôi gần gũi hơn với kết quả mà tôi yêu cầu. Mặc dù tôi thực sự ước rằng tôi phải tự do để tạo ra thực thể của riêng mình bắt chước thực thể Class. Có vẻ như, tuy nhiên, một sự đồng thuận đang tăng lên chống lại khả năng đó. – JnBrymn

8

Âm thanh như duck typing với tôi. Chỉ cần khai báo các phương pháp mà bạn muốn và hãy nhớ rằng nó dễ dàng hơn để cầu xin tha thứ hơn phép:

try: 
    poodle.wear() 
except (AttributeError, TypeError): 
    pass 
+0

+1 cho gõ vịt có lẽ là những gì OP có thể sử dụng –

2

Trong Python bạn có thể thay đổi các thừa kế của một lớp trong thời gian chạy, nhưng tại mỗi thời điểm nhất định một lớp không phải là một lớp con của người khác trừ khi được tuyên bố khác. Không có "có thể hoặc có thể không" - đó sẽ cần logic bậc ba mà Python không hỗ trợ. Nhưng tất nhiên bạn có thể viết các hàm "Is-a" và "Has-a" của riêng bạn để ánh xạ các bản thể OWL vào các lớp Python.

1

Tôi nghĩ dựa vào cấu trúc lớp, bất kể động lực, là bước lùi khi biểu diễn thông tin với giả định từ mở.

Các lớp làm mẫu và đối tượng phân phát dưới dạng các trường hợp hoàn toàn không có lợi thế khi được sử dụng với OWA. Hãy xem xét một lớp người mà chúng tôi mã hóa kiến ​​thức rằng một người có 2 chân. Tuy nhiên, chúng tôi không thể suy ra rằng một cá thể của Người sẽ có hai chân, vì người đó có thể bị khuyết tật.

Nếu thuộc tính lớp không có ý nghĩa như trong ví dụ trên, có vẻ như ít điểm khi sử dụng chúng hoặc bất kỳ cấu trúc phân cấp nào khác để mã hóa thông tin.

+0

Tôi cần làm rõ ở đây rằng, hiện tại, tôi không quan tâm đến việc ý định của tôi có hợp lý hay không. Thay vào đó, tôi chỉ muốn biết liệu tôi có thể sử dụng Ruby để tạo ra một thực thể * Lớp giống * để thay thế thực thể Class hiện tại hay không. Điều đó đang được nói, bạn có một số điểm tốt, và ngay cả khi tôi tạo ví dụ "chó có 4 chân", tôi nhận ra rằng nó quá đơn giản. Tuy nhiên tôi có một số điều khác trong tâm trí mà vẫn làm cho tôi rất quan tâm đến việc tạo ra một lớp học thế giới mở. – JnBrymn

6

Không, bạn không thể làm điều đó trong Ruby. Trong Ruby, mô hình đối tượng được nướng vào language specification và không thể truy cập được (và chắc chắn không phải là có thể sửa đổi) từ bên trong chương trình. Ngay cả trong Rubinius, là một triển khai Ruby được viết chủ yếu trong Ruby, và với khả năng siêu lập trình tuyệt vời mở rộng vượt xa những gì đặc tả kỹ thuật của Ruby cung cấp, một số the fundamental primitives are hardwired in C++.

Tôi không quen thuộc lắm với Python, nhưng tôi chắc chắn nó giống như vậy, ngay cả trong PyPy.

Bạn thể có thể làm điều đó trong Smalltalk, bằng cách sửa đổi (hoặc subclassing) the Behavior class, đó là lớp cha của Class và xác định hành vi của cả hai lớp và metaclasses.

Bạn có thể chắc chắn làm điều đó trong CLOS hoặc chính xác hơn bằng cách sử dụng CLOS's MOP (Meta-Object Protocol). Sau khi tất cả, đó là những gì một MOP là cho: xác định mô hình đối tượng.

Khái niệm OO gần nhất với những gì bạn mô tả có vẻ là của Predicate Classes.Một biến vị ngữ là một lớp mà các cá thể của nó không được định nghĩa tĩnh, nhưng bởi một tập hợp các biến vị ngữ: tất cả các đối tượng thỏa mãn tập hợp các biến vị ngữ là các cá thể của lớp, ngay sau và miễn là vị ngữ giữ. Trong một ngôn ngữ có trạng thái có thể thay đổi, điều này rõ ràng có nghĩa là các đối tượng có thể "di chuyển" vào và ra khỏi các lớp biến vị ngữ khi trạng thái của chúng thay đổi. Nó cũng có nghĩa là tại bất kỳ thời điểm nào, một đối tượng có thể là một thể hiện của nhiều hoặc không có các lớp vị ngữ.

Ngôn ngữ chính thống duy nhất (cho một định nghĩa khá rộng về "chủ đạo") Tôi biết điều đó có các lớp vị ngữ là Factor.

Tuy nhiên, xin lưu ý rằng ngay cả ở đây, các biến vị ngữ được xác định và một đối tượng hoặc là hoàn thành chúng hoặc không. Không có khái niệm về việc khám phá xem một đối tượng có hoàn thành một biến vị ngữ trong thời gian chạy hay không.

Ý tưởng của Clojure là ý tưởng của ad-hoc taxonomy.

Cuối cùng, nhưng chắc chắn không kém, bạn có thể xem hệ thống đối tượng Mikel Evins được gọi là Categories. Mô tả tốt nhất của hạng mục, là chỉ cần làm theo các mục blog trong thứ tự thời gian:

  1. Protocols
  2. Categories
  3. A peek at Categories
  4. No Kings in Rome
  5. Up pops a reasonable facsimile thereof
  6. Different Categories of Categories
  7. Categories Bugs
  8. Flat Cat in a C3 Vat
  9. Categories 0.2
  10. Bard
  11. Bard intricacies

Trong tương lai, hầu hết các phát triển vào Danh mục sẽ được thực hiện trong ngôn ngữ mới Mikel của Bard và bạn có thể làm theo sự tiến bộ của họ bằng cách làm theo the Categories tagthe Bard tag trên Mikel's new blog.

Tuy nhiên, nói chung, tôi sẽ nói rằng thực tế là quản lý kiến ​​thức và hướng đối tượng đều sử dụng từ lớp chủ yếu là một tai nạn lịch sử. Tôi không nghĩ rằng mô hình hóa với người khác là phù hợp.

+0

Thông tin rất tốt Jörg. Cảm ơn bạn đã thu hút sự chú ý đến khái niệm Predicate Class. Nó rất giống với những gì tôi muốn, mặc dù với một ngoại lệ lớn mà bạn đã chỉ ra: trong một lớp Predicate nếu đối tượng không thỏa mãn vị từ thì nó được biết là không ở trong lớp đó. Tôi muốn giữ lại tùy chọn thứ ba là "Tôi không biết nếu nó ở trong lớp đó." Vì vậy, nếu tôi quyết định đẩy xa hơn, tôi vẫn sẽ phải tạo lại một lớp như đối tượng. Tôi vẫn hy vọng một số cách để làm điều này trong ruby. Thay vì lập trình lại lớp, tôi có thể kế thừa từ Module và tạo OpenClass không? – JnBrymn

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