Câu hỏi Tại sao eigenclass không tương đương với self.class, khi nó trông rất giống nhau?


Tôi đã bỏ lỡ bản ghi nhớ ở đâu đó và tôi hy vọng bạn sẽ giải thích điều này với tôi.

Tại sao eigenclass của một đối tượng khác với self.class?

class Foo
  def initialize(symbol)
    eigenclass = class << self
      self
    end
    eigenclass.class_eval do
      attr_accessor symbol
    end
  end
end

Tàu của tôi về logic tương đương với eigenclass với class.self khá đơn giản:

class << self là một cách khai báo các phương thức lớp, chứ không phải là các phương thức thể hiện. Đó là lối tắt đến def Foo.bar.

Vì vậy, trong tham chiếu đến đối tượng lớp, quay trở lại self phải giống hệt nhau self.class. Điều này là bởi vì class << self sẽ đặt self đến Foo.class để định nghĩa các phương thức / thuộc tính lớp.

Tôi chỉ bối rối? Hoặc, đây có phải là thủ thuật lén lút của chương trình siêu lập trình Ruby không?


76
2017-10-27 13:31


gốc




Các câu trả lời:


class << self không chỉ là cách khai báo các phương thức lớp (mặc dù nó có thể được sử dụng theo cách đó). Có lẽ bạn đã thấy một số cách sử dụng như:

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

Điều này hoạt động và tương đương với def Foo.a, nhưng cách nó hoạt động là một chút tinh tế. Bí mật là self, trong bối cảnh đó, đề cập đến đối tượng Foo, có lớp là một phân lớp duy nhất, ẩn danh của Class. Phân lớp này được gọi là Foo'S eigenclass. Vì thế def a tạo ra một phương pháp mới gọi là a trong Foo's eigenclass, có thể truy cập bằng cú pháp gọi phương thức thông thường: Foo.a.

Bây giờ hãy xem một ví dụ khác:

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

Ví dụ này cũng giống như ví dụ cuối cùng, mặc dù nó có thể khó nói lúc đầu. frob được xác định, không phải trên String lớp học, nhưng trên eigenclass của str, một lớp con ẩn danh duy nhất của String. Vì thế str có một frob phương pháp, nhưng trường hợp của String nói chung thì không. Chúng ta cũng có thể có các phương thức String bị ghi đè (rất hữu ích trong một số kịch bản thử nghiệm khó khăn).

Bây giờ chúng tôi được trang bị để hiểu ví dụ ban đầu của bạn. Phía trong Foophương thức khởi tạo, self không đề cập đến lớp Foo, nhưng đối với một số cụ thể ví dụ của Foo. Eigenclass của nó là một phân lớp của Foo, Nhưng nó không phải như vậy Foo; nó không thể được, hoặc người nào khác các trick chúng ta đã thấy trong ví dụ thứ hai không thể làm việc. Vì vậy, để tiếp tục ví dụ của bạn:

f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)

f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.

Hi vọng điêu nay co ich.


114
2017-10-27 13:59



Mỗi trường hợp lớp học là một lớp con ẩn danh của lớp được tạo ra. Lớp của f1 là lớp con ẩn danh của Foo, lớp của Foo là một lớp con ẩn danh của Lớp. - David Seiler
Câu trả lời hay :) rất nhiều người không hiểu điều này rõ ràng như bạn. - horseyguy
Không bao giờ thực sự hiểu điều này cho đến khi tôi đọc câu trả lời của bạn! :) - Nikki Erwin Ramirez
Làm thế nào là eigenclass của f1 khác nhau sau đó, khái niệm, từ trường hợp thực tế của f1. Nếu f1 là trường hợp duy nhất có bao giờ có quyền truy cập vào các phương pháp của eigenclass của nó, không phân biệt giữa f1 và loại eigenclass của nó bị phá vỡ? - elju
@elju Yeah, kinda. Sự khác biệt thực sự quan trọng là giữa "Foo" và "eigenclass f1"; nếu bạn có điều đó, bạn có thể ổn. - David Seiler


Câu trả lời đơn giản nhất: eigenclass không thể được khởi tạo.

class F
 def eigen
  class << self 
   self
  end
 end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class

44
2017-11-16 16:09



bạn có thể chỉ có 1 điểm trên trang web này, nhưng tôi thích bạn và phong cách của bạn. - horseyguy
Đồng ý w / banister; đây là một câu trả lời tuyệt vời - Christopher Scott
Thông tin thú vị, nhưng không trả lời câu hỏi - Alexey
Đây là một nhận xét cực kỳ hữu ích và sâu sắc mà IFF đã đọc câu trả lời của @ DavidSeiler ở trên. - Jazz
Theo sức mạnh ở đây là demo'ing ngoại lệ được nâng lên. - New Alexandria


Yehuda Katz làm một công việc khá tốt để giải thích sự tinh tế trong "Metaprogramming trong Ruby: Đó là tất cả về bản thân"


11
2017-12-21 01:38



phụ đề hay ... subtleties? ;) - horseyguy
doh :) Cảm ơn vì đã phát hiện ra điều đó, đã được khắc phục ngay bây giờ. - Pete Hodgson
Không cố định thực sự - Kamil Lelonek