Ne gelmez class << self
yapmak Ruby ?
Ne gelmez class << self
yapmak Ruby ?
Yanıtlar:
İlk olarak, class << foo
sözdizimi foo
singleton sınıfını (eigenclass) açar . Bu, söz konusu nesne üzerinde çağrılan yöntemlerin davranışını özelleştirmenize olanak tanır.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
: Şimdi soruyu cevaplamak için class << self
açılır self
yöntemler akım için yeniden tanımlanabilir böylece, 'in tekil sınıfını self
(bir sınıf veya modül vücut içinde sınıf olan veya modülü nesne kendisini ). Genellikle, bu sınıf / modül ("statik") yöntemlerini tanımlamak için kullanılır:
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Bu, steno olarak da yazılabilir:
class String
def self.value_of obj
obj.to_s
end
end
Veya daha da kısa:
def String.value_of obj
obj.to_s
end
Bir işlev tanımının içindeyken self
, işlevin çağrıldığı nesneyi ifade eder. Bu durumda, class << self
o nesne için singleton sınıfını açar; bunun bir kullanımı fakir bir insanın devlet makinesini uygulamaktır:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
Yani, yukarıdaki örnekte, her örneği StateMachineExample
olan process_hook
diğer adı process_state_1
, ama ikincisi de, bu yeniden tanımlamak nasıl notu process_hook
(için self
diğer etkilemeyen, sadece StateMachineExample
karşı örneklerini) process_state_2
. Bu nedenle, bir çağıran process
yöntemi her yeniden çağırdığında (yeniden tanımlanabilir çağrıyı çağırır process_hook
), davranış, bulunduğu duruma bağlı olarak değişir.
class << self
sınıf / modül yöntemleri oluşturmak için daha yaygın bir kullanımdır . class << self
Çok daha deyimsel bir kullanım olduğu için muhtemelen bu kullanımı genişleteceğim .
a
'S singleton_class
beri a
' s sınıfına (değiştikten sonra inspect
) String
sınıfın benzersiz bir varyantı olduğunu söylemek gerçekten kafa karıştırıcı . Tekil String
sınıf değiştiriyor olsaydı, diğer tüm String
örnekleri etkilerdi. Ne hala daha tuhaf var daha sonra yeniden eğer olmasıdır String
yeniden tanımlamak için inspect
daha sonra a
hala yeni değişiklikleri toplayacak.
class << self
Değerinin ötesinde self
, blok kapsamındaki singleton sınıfına eşit olan bir şey ifade ediyor mu ?
Ben yaklaşık süper basit bir açıklaması buldum class << self
, Eigenclass
ve yöntemlerinin farklı türde.
Ruby'de, bir sınıfa uygulanabilecek üç tür yöntem vardır:
Örnek yöntemleri ve sınıf yöntemleri, diğer programlama dillerindeki adlarıyla neredeyse benzerdir.
class Foo
def an_instance_method
puts "I am an instance method"
end
def self.a_class_method
puts "I am a class method"
end
end
foo = Foo.new
def foo.a_singleton_method
puts "I am a singletone method"
end
Bir Eigenclass
(tekton yöntemlerini içeren) erişmenin başka bir yolu da aşağıdaki sözdizimidir ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
şimdi bu bağlamda self
sınıfın Foo
kendisi olan tekli bir yöntem tanımlayabilirsiniz :
class Foo
class << self
def a_singleton_and_class_method
puts "I am a singleton method for self and a class method for Foo"
end
end
end
foo.singleton_class.instance_methods(false)
kontrol etmek için kullanabilirsiniz .
Genellikle örnek yöntemleri global yöntemlerdir. Bu, tanımlandıkları sınıfın tüm örneklerinde mevcut oldukları anlamına gelir. Buna karşılık, tek bir nesneye tekil bir yöntem uygulanır.
Ruby yöntemleri sınıflarda saklar ve tüm yöntemler bir sınıfla ilişkilendirilmelidir. Tekton yönteminin tanımlandığı nesne bir sınıf değildir (bir sınıfın örneğidir). Yalnızca sınıflar yöntemleri depolayabilirse, bir nesne nasıl bir singleton yöntemini depolayabilir? Tekli bir yöntem oluşturulduğunda, Ruby otomatik olarak bu yöntemi saklamak için anonim bir sınıf oluşturur. Bu anonim sınıflara, tek sınıf veya öz sınıflar olarak da bilinen metasınıflar denir. Singleton yöntemi, singleton yönteminin tanımlandığı nesne ile ilişkili olan metasınıf ile ilişkilidir.
Tek bir nesne içinde birden çok tekli yöntem tanımlanmışsa, hepsi aynı metasınıfta saklanır.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
Yukarıdaki örnekte, << z1 sınıfı, geçerli benliği z1 nesnesinin metasınıfına işaret edecek şekilde değiştirir; sonra metasınıf içindeki say_hello yöntemini tanımlar.
Sınıflar ayrıca nesnelerdir (yerleşik sınıfın Class adı verilen örnekleri). Sınıf yöntemleri, bir sınıf nesnesiyle ilişkili singleton yöntemlerinden başka bir şey değildir.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Tüm nesnelerin metasınıfları olabilir. Bu, sınıfların metasınıfları da olabileceği anlamına gelir. Yukarıdaki örnekte, sınıf << kendini değiştirir, böylece Zabuton sınıfının metasınıfına işaret eder. Bir yöntem açık bir alıcı olmadan tanımlandığında (yöntemin tanımlanacağı sınıf / nesne), geçerli kapsamda, yani kendiliğin geçerli değeri içinde dolaylı olarak tanımlanır. Bu nedenle, stuff yöntemi Zabuton sınıfının metasınıfında tanımlanır. Yukarıdaki örnek, sınıf yöntemini tanımlamanın başka bir yoludur. IMHO, kodun anlaşılmasını kolaylaştırdığı için sınıf yöntemlerini tanımlamak için def self.my_new_clas_method sözdizimini kullanmak daha iyidir. Yukarıdaki örnek dahil edildi, bu yüzden sınıf << kendi sözdizimiyle karşılaştığımızda ne olduğunu anlıyoruz.
Ek bilgiler bulunabilir Yakut Sınıflar hakkında bu yazı .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[ self == thing.singleton_class
bloğu bağlamında yapar ] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
Nesne devralır Onun #methods
onun ile ilgili #singleton_class.instance_methods
ve daha sonra onun arasından #class.instance_methods
.
Burada verdi hi
'ın tekil sınıf örneği yöntemini :a
. Bunun yerine << hi sınıfı ile yapılabilirdi .
hi
's #singleton_class
tüm örnek yöntemleri vardır hi
' s #class
ve muhtemelen biraz daha ( :a
burada).
[nesnelerin örnek yöntemleri #class
ve #singleton_class
doğrudan nesneye uygulanabilir. ruby thing.a'yı gördüğünde, önce şunu arar: thing.singleton_class.instance_methods ve sonra thing.class.instance_methods'da bir yöntem tanımı
Bu arada - nesnenin singleton class == metaclass == eigenclass diyorlar .
Eşdeğerinde tekil yöntem tek bir nesne için yalnızca tanımlanan bir yöntemdir.
Misal:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods
Singleton'ın SomeClass yöntemleri
Ölçek
Singleton'ın test_obj yöntemleri
test_2
test_3
Aslında, Ruby projeleriniz için herhangi bir C uzantısı yazarsanız, bir Modül yöntemini tanımlamanın tek bir yolu vardır.
rb_define_singleton_method
Bu kendi işinin sadece her türlü soruyu açtığını biliyorum, böylece her bir parçayı arayarak daha iyisini yapabilirsiniz.
Önce nesneler.
foo = Object.new
Foo için bir yöntem yapabilir miyim?
Elbette
def foo.hello
'hello'
end
Bununla ne yapacağım?
foo.hello
==>"hello"
Sadece başka bir nesne.
foo.methods
Tüm Object yöntemlerini ve yenisini alırsınız.
def foo.self
self
end
foo.self
Sadece foo nesnesi.
Sınıf ve Modül gibi diğer Nesneler'den foo yaparsanız ne olduğunu görmeye çalışın. Tüm cevaplardan örnekler oynamak güzel ama kodun yazılma biçiminde neler olup bittiğini gerçekten anlamak için farklı fikirler veya konseptlerle çalışmanız gerekiyor. Şimdi bakmanız gereken birçok terim var.
Singleton, Class, Module, self, Object ve Eigenclass gündeme getirildi, ancak Ruby Nesne Modellerini bu şekilde adlandırmıyor. Daha çok Metaclass gibi. Richard veya __neden sana buradaki fikri neden gösterir. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html Ve sizi uçurursa, aramada Ruby Nesne Modelini aramayı deneyin. YouTube'da bildiğim iki video Dave Thomas ve Peter Cooper. Bu kavramı da açıklamaya çalışıyorlar. Dave'in bunu alması uzun zaman aldı, bu yüzden endişelenme. Ben de hala üzerinde çalışıyorum. Neden başka burada olabilirim? Sorunuz için teşekkürler. Ayrıca standart kütüphaneye de bakınız. Tıpkı bir FYI gibi bir Singleton Modülüne sahiptir.
Bu oldukça iyi. https://www.youtube.com/watch?v=i4uiyWA8eFk