පංතිය << රූබි හි ස්වයං මෝඩකම


885

කුමක්ද කරන්නේ class << selfකරන්න රූබි ?


35
යෙහුඩා කැට්ස් විසින් ලියන ලද මෙම මාතෘකාව පිළිබඳ ඉතා හොඳ ලිපියක් ඇත: yehudakatz.com/2009/11/15/… සහ යුගුයි: yugui.jp/articles/846
ඇන්ඩ්‍රි

3
මෙහි තවත් සුපිරි ලස්සන
ලිපියක්

2
මම මෙය මොඩියුලයක ඇතුළත දකිමි, එය වෙනස් වේද? github.com/ruby/rake/blob/master/lib/rake/rake_module.rb
විලියම් එන්ට්‍රිකන්

UllFullDecent රූබී හි ඇති සියල්ල මොඩියුල සහ පන්ති ඇතුළු වස්තුවක් බැවින් එය වෙනසක් නොකරයි.
ආරොන්

1
බලන්න github.com/defunkt/metaid/blob/master/metaid.rb එය "පැහැදිලිවම Metaclasses දුටු" එක්ක යනවා viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html
ඩග්ලස් ජී ඇලන්

Answers:


927

පළමුව, class << fooසින්ටැක්ස් fooසිංගල්ටන් පංතිය (අයිජන් ක්ලාස්) විවෘත කරයි . මෙම නිශ්චිත වස්තුව මත කැඳවන ක්‍රම වල හැසිරීම විශේෂීකරණය කිරීමට මෙය ඔබට ඉඩ සලසයි.

a = 'foo'
class << a
  def inspect
    '"bar"'
  end
end
a.inspect   # => "bar"

a = 'foo'   # new object, new singleton class
a.inspect   # => "foo"

දැන්, ප්‍රශ්නයට පිළිතුරු සැපයීම සඳහා: වත්මන් වස්තුව සඳහා ක්‍රම නැවත අර්ථ දැක්විය හැකි වන පරිදි ( සිංගල්ටන් පන්තිය class << selfවිවෘත කරයි) (පන්තියක් හෝ මොඩියුලයක් තුළ පන්තිය හෝ මොඩියුලයම වේ ). සාමාන්‍යයෙන්, මෙය පන්ති / මොඩියුල ("ස්ථිතික") ක්‍රම නිර්වචනය කිරීමට භාවිතා කරයි:selfself

class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # => "42"

මෙය කෙටියෙන් ද ලිවිය හැකිය:

class String
  def self.value_of obj
    obj.to_s
  end
end

හෝ ඊටත් වඩා කෙටි:

def String.value_of obj
  obj.to_s
end

ශ්‍රිත අර්ථ දැක්වීමක් තුළ ඇති විට, ශ්‍රිතය selfකැඳවනු ලබන වස්තුවට යොමු වේ. මෙම අවස්ථාවේදී, class << selfඑම වස්තුව සඳහා සිංගල්ටන් පන්තිය විවෘත කරයි; එහි එක් භාවිතයක් වන්නේ දුප්පතාගේ රාජ්‍ය යන්ත්‍රය ක්‍රියාත්මක කිරීමයි.

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

එබැවින්, ඉහත උදාහරණයේ දී, සෑම අවස්ථාවක්ම වෙනස් StateMachineExampleවී process_hookඇත process_state_1, නමුත් දෙවැන්නෙහි එය නැවත අර්ථ දැක්විය හැක්කේ කෙසේදැයි බලන්න process_hook( selfවෙනත් StateMachineExampleඅවස්ථාවන්ට පමණක් බලපාන්නේ නැත ) process_state_2. එබැවින්, ඇමතුම්කරුවෙකු processක්‍රමයට කතා කරන සෑම අවස්ථාවකම (එය නැවත අර්ථ දැක්විය හැකි යැයි කියනු ලැබේ process_hook), හැසිරීම වෙනස් වන්නේ එය කුමන තත්වයකද යන්න මතය.


23
@ J :rg: සංස්කරණය සඳහා +1 (සංස්කරණයන් ඉහළ නැංවීමේ හැකියාව SO විසින් සපයනු ඇතැයි මම ප්‍රාර්ථනා කරමි. class << selfපංති / මොඩියුල ක්‍රම නිර්මාණය කිරීම සඳහා එය වඩාත් පොදු භාවිතයකි . මම බොහෝ විට එම භාවිතය පුළුල් කරමි class << self, මන්ද එය වඩාත් මුග්ධ භාවිතයකි.
ක්‍රිස් ජෙස්ටර්-යං

4
! gsub ( "eigenclass", "තනි පන්ති"), ඉදිරියේදී පැවැත්වීමට නියමිත ක්රමය බලන්න redmine.ruby-lang.org/repositories/revision/1?rev=27022
මාක්-ඇන්ඩෲ Lafortune

4
පංතියේ (වෙනස් වීමෙන් පසු ) පන්තියේ අද්විතීය ප්‍රභේදයක් බැවින් 's a' වෙත යොමු කිරීම ඇත්තෙන්ම ව්‍යාකූල ය . එය සිංගල්ටන් පන්තිය වෙනස් කරන්නේ නම් එය අනෙක් සියලුම අවස්ථාවන්ට බලපායි . දේ තවමත් අමානුෂික තියෙන්නේ ඔබට පසුව නැවත විවෘත වන්නේ නැති බව දක්වන ලෙසට එවකට තවමත් නව වෙනස්කම් ගන්න වනු ඇත. singleton_classainspectStringStringStringStringinspecta
ඕල්ඩ් ප්‍රෝ

1
OldOldPro මැට්ස් ද පවසන පරිදි මම තවමත් ඊජන් ක්ලාස් යන නමට කැමැත්තෙමි. නමුත්, සෑම කෙනෙකුම සතුටු කළ නොහැක, මම හිතන්නේ.
ක්‍රිස් ජෙස්ටර්-යං

5
"වස්තුවක සිංගල්ටන් පංතිය විවෘත කරයි" යන ප්‍රකාශය මට හමු විය - මා මීට පෙර කිහිප වතාවක් කියවා ඇති - නොපැහැදිලි. මගේ දැනුමට අනුව, රූබි ලියකියවිලි වල කොතැනකවත් අර්ථ දක්වා ඇති පන්තියක් "විවෘත කිරීම" නැත, අප සියලු දෙනාටම එහි තේරුම පිළිබඳ අදහසක් තිබුණද. කරන්නේ class << selfවටිනාකම වඩා නපුරු දෙයක් self, වාරණ ගේ විෂය පථය තුල කටය පන්ති සමාන සකස්?
කැරි ස්වෝව්ලන්ඩ්

39

මම මේ ගැන සුපිරි සරල පැහැදිලි කිරීමක් සොයා class << self, Eigenclassසහ ක්රම විවිධ වර්ගයේ.

රූබි හි, පන්තියකට යෙදිය හැකි ක්‍රම තුනක් තිබේ:

  1. උදාහරණ ක්‍රම
  2. තනි ක්‍රම
  3. පන්ති ක්‍රම

උදාහරණ ක්‍රම සහ පන්ති ක්‍රම වෙනත් ක්‍රමලේඛන භාෂාවල ඒවායේ සමජාතීයතාවයට බොහෝ දුරට සමාන ය.

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

Eigenclass(සිංගල්ටන් ක්‍රම ඇතුළත්) වෙත ප්‍රවේශ විය හැකි තවත් ක්‍රමයක් වන්නේ පහත දැක්වෙන වාක්‍ය ඛණ්ඩයයි class <<:

foo = Foo.new

class << foo
  def a_singleton_method
    puts "I am a singleton method"
  end
end

මෙම සන්දර්භය තුළ selfපන්තියම වන සිංගල්ටන් ක්‍රමයක් දැන් ඔබට අර්ථ දැක්විය හැකිය Foo:

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

4
ඇත්ත වශයෙන්ම සිංගල්ටන් ක්‍රම සහ පන්ති ක්‍රම එක සමාන වේ, මේ දෙකම සිංගල්ටන් පන්තියේ පවතී. ඔබට foo.singleton_class.instance_methods(false)පරීක්ෂා කිරීමට භාවිතා කළ හැකිය .
ඩේමන් යුවාන්

24

සාමාන්‍යයෙන් නිදර්ශන ක්‍රම ගෝලීය ක්‍රම වේ. එයින් අදහස් කරන්නේ ඒවා අර්ථ දක්වා ඇති පන්තියේ සෑම අවස්ථාවකම ඒවා ලබා ගත හැකි බවයි. ඊට වෙනස්ව, තනි වස්තුවක් මත සිංගල්ටන් ක්‍රමයක් ක්‍රියාත්මක වේ.

පන්තිවල රූබි ගබඩා කිරීමේ ක්‍රම සහ සියලුම ක්‍රම පන්තියක් සමඟ සම්බන්ධ විය යුතුය. සිංගල්ටන් ක්‍රමයක් නිර්වචනය කරන වස්තුව පන්තියක් නොවේ (එය පන්තියක නිදසුනකි). පංතිවලට පමණක් ක්‍රම ගබඩා කළ හැකි නම්, වස්තුවකට සිංගල්ටන් ක්‍රමයක් ගබඩා කරන්නේ කෙසේද? සිංගල්ටන් ක්‍රමයක් නිර්මාණය කළ විට, රූබි ස්වයංක්‍රීයව එම ක්‍රමය ගබඩා කිරීම සඳහා නිර්නාමික පන්තියක් නිර්මාණය කරයි. මෙම නිර්නාමික පංති මෙටාක්ලාස් ලෙස හැඳින්වේ, එය සිංගල්ටන් පංති හෝ අයිජන් ක්ලාස් ලෙසද හැඳින්වේ. සිංගල්ටන් ක්‍රමය මෙටාක්ලාස් සමඟ සම්බන්ධ වන අතර අනෙක් අතට සිංගල්ටන් ක්‍රමය අර්ථ දක්වා ඇති වස්තුව සමඟ සම්බන්ධ වේ.

තනි වස්තුවක් තුළ බහු සිංගල්ටන් ක්‍රම නිර්වචනය කර ඇත්නම්, ඒවා සියල්ලම එකම මෙටාක්ලාස් තුළ ගබඩා වේ.

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'…

ඉහත උදාහරණයේ දී, පංතිය << z1 වත්මන් ආත්මය z1 වස්තුවෙහි මෙටාක්ලාස් වෙත යොමු කරයි. ඉන්පසු එය මෙටාක්ලාස් තුළ ඇති say_hello ක්‍රමය අර්ථ දක්වයි.

පංති යනු වස්තූන් ද වේ. පන්ති ක්‍රම යනු පන්ති වස්තුවක් හා සම්බන්ධ සිංගල්ටන් ක්‍රමවලට වඩා වැඩි දෙයක් නොවේ.

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

සියලුම වස්තූන්හි මෙටාක්ලාස් තිබිය හැක. ඒ කියන්නේ පන්තිවලට මෙටාක්ලාස් ද තිබිය හැකිය. ඉහත උදාහරණයේ දී, පංතිය << ස්වයං ස්වයං වෙනස් කිරීම නිසා එය සැබුටන් පන්තියේ මෙටාක්ලාස් වෙත යොමු කරයි. පැහැදිලි ග්‍රාහකයක් නොමැතිව ක්‍රමයක් නිර්වචනය කළ විට (ක්‍රමය නිර්වචනය කරනු ලබන පන්තිය / වස්තුව), එය වත්මන් විෂය පථය තුළ ව්‍යංගයෙන් අර්ථ දැක්වේ, එනම් ස්වයං අගය. එබැවින්, සැබුටන් පන්තියේ මෙටාක්ලාස් තුළ දේවල් ක්‍රමය අර්ථ දක්වා ඇත. ඉහත උදාහරණය පන්ති ක්‍රමයක් අර්ථ දැක්වීමට තවත් ක්‍රමයක් පමණි. IMHO, පන්ති ක්‍රම නිර්වචනය කිරීම සඳහා def self.my_new_clas_method සින්ටැක්ස් භාවිතා කිරීම වඩා හොඳය, එය කේතය තේරුම් ගැනීමට පහසු කරයි. ඉහත උදාහරණය ඇතුළත් කර ඇති නිසා පන්තිය << ස්වයං වාක්‍ය ඛණ්ඩය හරහා පැමිණෙන විට සිදුවන්නේ කුමක්ද යන්න අපට වැටහේ.

රූබි පංති පිළිබඳ අමතර තොරතුරු මෙම ලිපියෙන් සොයාගත හැකිය .


16

කුමන පන්තිය << දේ කරන්නේ:

class Hi
  self #=> Hi
  class << self #same as 'class << Hi'
    self #=> #<Class:Hi>
    self == Hi.singleton_class #=> true
  end
end

[එය එහි වාරණයේ self == thing.singleton_class සන්දර්භය තුළ කරයි] .


කුමක්ද. සිංගල්ටන්_ ක්ලාස් යනු කුමක්ද?

hi = String.new
def hi.a
end

hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true

hiවස්තුව උරුම වන්නේ එහි #methodsසිට #singleton_class.instance_methodsපසුව ය #class.instance_methods.
මෙන්න අපි දුන්නා hiගේ කටය පන්ති උදාහරණයක් ක්රමය :a. පංතිය << හායි වෙනුවට එය කළ හැකිව තිබුණි .
hiගේ #singleton_classසියලු උදාහරණයක් ක්රම ඇත his '' #class(සමහර වැඩි විය හැකි ඇති අතර, :aමෙහි).

[උදාහරණ ලෙස දේවල් ක්‍රම #class සහ #singleton_class ඒවා කෙලින්ම යෙදිය හැකිය. රූබි විසින් දෙයක් දකින විට, එය මුලින්ම සොයන්නේ: thing.singleton_class.instance_methods හි ක්‍රම නිර්වචනයක් සහ පසුව thing.class.instance_methods]


මාර්ගය වන විට - ඔවුන් වස්තුව ගේ කතා කටය පන්ති == metaclass == eigenclass .


3

А සිංගල්ටන් ක්‍රමය යනු තනි වස්තුවකට පමණක් අර්ථ දක්වා ඇති ක්‍රමයකි.

උදාහරණයක්:

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

සොම් ක්ලාස් හි සිංගල්ටන්ගේ ක්‍රම

පරීක්ෂණය


Test_obj හි සිංගල්ටන්ගේ ක්‍රම

test_2

test_3


1

ඇත්ත වශයෙන්ම ඔබ ඔබේ රූබි ව්‍යාපෘති සඳහා සී දිගුවන් ලියන්නේ නම් මොඩියුල ක්‍රමයක් නිර්වචනය කිරීමට ඇත්තේ එක් මාර්ගයක් පමණි.

rb_define_singleton_method

මෙම ස්වයං ව්‍යාපාරය වෙනත් සියලු ආකාරයේ ප්‍රශ්න විවෘත කරන බව මම දනිමි, එවිට ඔබට එක් එක් කොටස සෙවීමෙන් වඩා හොඳ කළ හැකිය.

වස්තු පළමුව.

foo = Object.new

මට foo සඳහා ක්‍රමයක් කළ හැකිද?

ෂුවර්

def foo.hello
 'hello'
end

මා එය කරන්නේ කුමක් ද?

foo.hello
 ==>"hello"

තවත් වස්තුවක් පමණි.

foo.methods

ඔබට සියලු වස්තු ක්‍රම සහ ඔබේ නව ක්‍රමය ලැබේ.

def foo.self
 self
end

foo.self

යන්තම් foo Object.

පංතිය සහ මොඩියුලය වැනි වෙනත් වස්තූන්ගෙන් ඔබ මෝඩයින් කළහොත් කුමක් සිදුවේදැයි බැලීමට උත්සාහ කරන්න. සියලු පිළිතුරු වලින් නිදසුන් සමඟ සෙල්ලම් කිරීම සතුටක් නමුත් කේතය ලියා ඇති ආකාරය සමඟ සිදුවන්නේ කුමක්ද යන්න සැබවින්ම තේරුම් ගැනීමට ඔබට විවිධ අදහස් හෝ සංකල්ප සමඟ වැඩ කළ යුතුය. ඉතින් දැන් ඔබට බැලීමට බොහෝ කොන්දේසි තිබේ.

සිංගල්ටන්, පංතිය, මොඩියුලය, ස්වයං, වස්තුව සහ අයිජන් ක්ලාස් ගෙන එන ලද නමුත් රූබි වස්තු ආකෘති ඒ ආකාරයෙන් නම් නොකරයි. එය මෙටාක්ලාස් වැනි ය. රිචඩ් හෝ __ ඇයි ඔබට මෙහි අදහස පෙන්වන්නේ. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html තවද ඔබට පහරක් එල්ල වුවහොත් සෙවීමේදී රූබි වස්තු ආකෘතිය බැලීමට උත්සාහ කරන්න. යූ ටියුබ් හි මා දන්නා වීඩියෝ දෙකක් ඩේව් තෝමස් සහ පීටර් කූපර් ය. ඔවුන් එම සංකල්පය ද පැහැදිලි කිරීමට උත්සාහ කරති. එය ලබා ගැනීමට ඩේව්ට බොහෝ කාලයක් ගත විය, එබැවින් කරදර නොවන්න. මම තවමත් ඒ පිළිබඳව කටයුතු කරමින් සිටිමි. වෙන ඇයි මම මෙහෙට ආවේ? ඔබගේ ප්‍රශ්නයට ස්තූතියි. සම්මත පුස්තකාලය දෙස බලන්න. එය FYI ලෙස සිංගල්ටන් මොඩියුලයක් ඇත.

මේක ගොඩක් හොඳයි. https://www.youtube.com/watch?v=i4uiyWA8eFk

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.