การใช้ตนเอง วิธีมิกซ์อิน และวิธีสัมผัส

นี่คือโค้ดบางส่วนที่ฉันใช้ในคลาสชื่อ Game:

def play
  puts "There are #{@players.length} players in #{@title}."

  @players.each do |n|
    puts n
   end

  @players.each do |o|
    GameTurn.take_turn(o)
    puts o
  end
end

ใช้บรรทัดโค้ดที่อ้างอิงถึงโมดูลที่เรียกว่า GameTurn ภายใน GameTurn ฉันมีวิธีที่เรียกว่า self.take_turn:

require_relative "die"
require_relative "Player"

module GameTurn

  def self.take_turn(o)
    die = Die.new

    case die.roll
    when 1..2
      o.blam
      puts "#{o.name} was blammed homie."
    when 3..4
      puts "#{o.name} was skipped." 
    else
      o.w00t
    end
  end
end

ฉันสับสนเล็กน้อยว่าทำไมเราถึงใช้ "ตนเอง" และความแตกต่างระหว่างวิธีการเปิดเผยและวิธีการมิกซ์อินในโมดูล ฉันถาม "วิธีการอินสแตนซ์ของคลาสเทียบกับวิธีโมดูล"

take_turn เป็นวิธีการแบบเปิดเผยจริงหรือ แม้ว่าเราจะป้อนอ็อบเจ็กต์จากคลาสผู้เล่นให้กับเมธอด take_turn แต่เมธอดนี้ยังถือว่าเป็นเมธอดโมดูลที่เราใช้โดยตรงหรือไม่ นี่ไม่ถือเป็นวิธีการมิกซ์อินใช่ไหม เรากำลังป้อนอ็อบเจ็กต์จากคลาสอื่นเข้าไปในเมธอด take_turn ดังนั้นมันจะไม่ปะปนกับคลาสอื่นใช่หรือไม่

นอกจากนี้ ฉันยังคงพยายามหาคำตอบว่าเมื่อใด/ทำไมเราถึงใช้คำว่า "ตนเอง"? ดูเหมือนแปลกที่เราต้องกำหนดวิธีการ take_turn ภายในโมดูล GameTurn โดยใช้คำว่า "self" ดูเหมือนว่ามันควรจะนิยามโดยไม่มี "ตัวตน" ไม่ใช่เหรอ?


person Jwan622    schedule 23.10.2014    source แหล่งที่มา
comment
เป็นไปได้ที่ซ้ำกันของ เหตุใดจึงนำหน้าเมธอดด้วย self   -  person infused    schedule 24.10.2014
comment
คุณมีคำถามมากเกินไป โปรดลดเหลือหนึ่งหรือสองอย่างมากที่สุดหากเกี่ยวข้องกันอย่างใกล้ชิด   -  person the Tin Man    schedule 24.10.2014


คำตอบ (1)


ตกลงตั้งแต่เริ่มต้น:

self ส่งคืนออบเจ็กต์ในบริบทที่ถูกดำเนินการเสมอ ดังนั้นที่นี่:

class A
  self     #=> A
end

ใน Ruby คุณสามารถกำหนดวิธีการให้กับวัตถุที่กำลังบินได้ ตัวอย่างเช่น:

o = Object.new

o.foo   #=> NameError 

def o.foo
  :foo
end

o.foo   #=> :foo

คลาสและโมดูลเป็นเพียงอ็อบเจ็กต์เหมือนกับอย่างอื่น ดังนั้นคุณจึงสามารถกำหนดวิธีการในคลาสและโมดูลเหล่านี้ได้เช่นกัน:

def A.method
  'class method'
end

A.method    #=> 'class_method'

อย่างไรก็ตาม มันง่ายกว่าและสะดวกกว่ามากที่จะกำหนดมันภายในเนื้อหาของคลาส - เนื่องจาก self ซึ่งจะส่งคืนคลาสเองเสมอ:

class A
  def self.foo
    :foo
  end
end

self ส่งคืน A ดังนั้นจึงสามารถอ่านได้เป็น:

class A
  def A.foo
    :foo
  end
end

ข้อดีของเรื่องนี้ก็คือ ถ้าคุณตัดสินใจเปลี่ยนชื่อคลาส คุณเพียงแค่ต้องเปลี่ยนชื่อคลาสที่ด้านบน ถัดจาก class - ส่วนที่เหลือจะจัดการเอง

ภายในเมธอด self จะเป็นผู้รับเมธอดเสมอ ดังนั้น:

o = Object.new
def o.method
  self
end
o.method == o       #=> true

มันอาจจะค่อนข้างสับสนในบางครั้ง ความสับสนทั่วไปมาจากโค้ด:

class A
  def get_class
    self.class
  end
end

class B < A
end

b = B.new
b.get_class     #=> B

แม้ว่า get_class จะถูกกำหนดไว้บนคลาส A แต่ self อ้างถึงตัวรับของเมธอด ไม่ใช่เจ้าของเมธอด ดังนั้นจึงประเมินเป็น:

b.class         #=> B

ด้วยเหตุผลเดียวกัน self ภายในเมธอดคลาสจะชี้ไปที่คลาสที่เมธอดถูกดำเนินการเสมอ

person BroiSatse    schedule 23.10.2014
comment
ชัดเจนมากและฉันติดตามคุณ หวังว่านี่จะช่วยเคลียร์คำถามเกี่ยวกับตัวเองให้ฉันก้าวไปข้างหน้า ขอบคุณ! - person Jwan622; 24.10.2014