2016-10-12 10 views
15

Có cách nào kiểm tra xem một đối tượng có một lớp đơn mà không tạo một lớp không?Làm thế nào để kiểm tra xem một đối tượng có một lớp đơn (eigenclass) mà không cần tạo một lớp

Khác với được nêu trong Check if an object has a singleton class, không đúng là mọi đối tượng đều có một lớp đơn (xem bằng chứng dưới https://repl.it/DuVJ/2).

Các phương pháp sau đây xuất hiện trong đầu của tôi, nhưng không có tác dụng:

  1. obj.singleton_class

    này sẽ tự động tạo ra một lớp singleton mới nếu không tồn tại (xem https://ruby-doc.org/core-1.9.2/Object.html#method-i-singleton_class).

  2. Sử dụng ObjectSpace:

    has_singleton_class = ObjectSpace.each_object(Class).any? do |klass| 
        klass < self.class && klass.singleton_class? && self.is_a?(klass) 
    end 
    

    này rất chậm và có thể không làm việc dưới JRuby như ObjectSpace có thể không có sẵn.

  3. obj.singleton_methods chỉ hoạt động nếu lớp singleton có ít nhất một phương pháp.

+2

vấn đề gì bạn đang cố gắng để giải quyết? Như Jörg đã viết trong câu trả lời liên kết, "Bất cứ khi nào bạn đi tìm một lớp singleton, nó sẽ ở đó." Trường hợp sử dụng của bạn là gì? –

+0

Chúng tôi đang làm việc trên https: // github.com/đường ray/đường ray/kéo/26771. Vấn đề là khi chúng ta thêm các lớp không mong muốn thông qua 'singleton_class', nó phá vỡ một số bài kiểm tra Rails kiểm tra số lớp. Chúng ta muốn đi qua 'self.singleton_class' nếu nó tồn tại, và nếu không gọi phương thức này là' self.class'. – Remo

+7

Ý kiến ​​của tôi là: 'ObjectSpace' cho phép bạn nhìn phía sau bức màn. Nhưng nếu bạn làm điều đó, bạn có thể thấy những thứ mà bạn không được thấy. Tôi đứng bởi sự khẳng định của tôi về câu hỏi được liên kết: các lớp singleton luôn tồn tại. Người thông dịch có thể chỉ có thể * thể chất * tạo ra chúng khi chúng cần thiết, nhưng mỗi khi bạn nhìn vào * kiểm tra * liệu có một, có * sẽ * là một hay không. Ví dụ, YARV luôn tạo các lớp đơn cho các mô đun và lớp, bất kể chúng có cần hay không, và nó không bao giờ tạo chúng cho các đối tượng khác, trừ khi bạn thực sự mở nó hoặc thêm một phương thức singleton. –

Trả lời

0

Bạn có thể sử dụng phương thức ancestors. Bởi vì bạn muốn kiểm tra xem một lớp (không phải là một đối tượng) là một singleton, bạn có thể lấy tất cả các mô-đun được trộn lẫn trong lớp và xác minh xem có bất kỳ một lớp nào là một lớp singleton hay không.

class Klass 
    include Singleton 
end 

Klass.ancestors.include? Singleton # true 

Trong ruby, để tạo một đĩa đơn, bạn nên bao gồm mô-đun Singleton. Vì vậy, nếu bạn kiểm tra cho mô-đun đó có nghĩa là lớp đó là một singleton. Việc thừa kế lớp cơ sở của Ruby của lớp mô-đun có nghĩa là bạn có quyền truy cập để sử dụng phương thức ancestors.

Tài liệu tham khảo:

  1. https://ruby-doc.org/core-2.1.0/Module.html#method-i-ancestors
  2. https://ruby-doc.org/core-2.2.0/Class.html
  3. https://ruby-doc.org/stdlib-2.1.0/libdoc/singleton/rdoc/Singleton.html#module-Singleton-label-Usage
+0

Cảm ơn câu trả lời của bạn. Trái ngược với ý thức chung, vấn đề này không phải là về mẫu đơn nhưng về một tính năng ruby ​​tiên tiến/interna gọi là "Eigenclass" mà, thật không may, cũng được gọi là "Singleton class". Về cơ bản, đây là một lớp tồn tại chỉ với một cá thể duy nhất và có thể khác với lớp cá thể "thực". Trong khi câu trả lời của bạn, trong chính nó, là hoàn toàn chính xác, tôi sợ nó không liên quan đến chủ đề trong tầm tay. – Remo

0

Phương pháp tổ tiên trả về một danh sách có thứ tự các lớp học và các module tương ứng với trình tự phương pháp tra cứu. ví dụ dưới đây, các cá thể của lớp CheckKlass sẽ tìm kiếm các phương thức trong CheckKlass, Object, Kernel và BasicObject trước khi gọi phương thức A # method_missing.

class CheckKlass; end 
CheckKlass.ancestors # => [CheckKlass, Object, Kernel, BasicObject] 

Và nếu Singleton được bao gồm điều này sẽ trông giống như dưới đây

class CheckKlass 
    include Singleton 
end 

Điều này có thể cung cấp cho bạn =>

[CheckKlass, Singleton, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, PP::ObjectMixin, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, ActiveSupport::Tryable, Kernel, BasicObject] 
Các vấn đề liên quan