วิธีการส่วนตัวใน Ruby?


95

บล็อกหรือบทแนะนำหรือหนังสือส่วนใหญ่มีวิธีการส่วนตัวที่ด้านล่างของชั้นเรียน / โมดูลใด ๆ นี่เป็นแนวทางปฏิบัติที่ดีที่สุดหรือไม่?

ฉันพบว่ามีวิธีการส่วนตัวที่สะดวกกว่าและเมื่อจำเป็น ตัวอย่างเช่น:

public
def my_method
  # do something
  minion_method
end

private
def minion_method
  # do something
end

public
def next_method
end

ด้วยวิธีนี้ฉันพบว่าโค้ดอ่านได้ง่ายขึ้นแทนที่จะเลื่อนขึ้นลงอย่างต่อเนื่องซึ่งน่ารำคาญมาก

วิธีนี้มีอะไรผิดพลาดอย่างร้ายแรงหรือไม่? การมีวิธีการส่วนตัวที่ด้านล่างไม่ใช่แค่แนวทางปฏิบัติที่ดีที่สุดและอย่างอื่นหรือไม่?


จริงๆแล้ววิธีของคุณก็ไม่เลวเช่นกัน ฉันก็ทำตามเหมือนกันในบางกรณีรู้สึกสะดวกกว่าprivate def my_method...end
r3bo0t

คำตอบ:


131

แนวทางปฏิบัติที่ดีที่สุดในมุมมองของฉันคือการไปตามลำดับและประกาศวิธีการของคุณโดยไม่ให้ความเป็นส่วนตัวในมุมมอง

ในตอนท้ายคุณสามารถทำให้วิธีการใด ๆ เป็นส่วนตัวได้โดยเพิ่ม: private :xmethod

ตัวอย่าง:

class Example
 def xmethod
 end

 def ymethod
 end

 def zmethod 
 end

 private :xmethod, :zmethod

end

สิ่งนี้เหมาะกับคำถามของคุณหรือไม่?


19
ฉันไม่คิดว่านี่เป็นความคิดที่ยอดเยี่ยมจากมุมมองของความสามารถในการอ่านได้เนื่องจากชั้นเรียนเติบโตขึ้นและยาวนานขึ้น
Alexander Suraphel

2
ฉันคิดว่าคุณควรจัดเรียงวิธีการตามลำดับความสำคัญและตามสิ่งที่เรียกว่าอะไรเมื่อสิ่งอื่น ๆ ทั้งหมดดูเหมือนเท่าเทียมกัน วิธีการส่วนตัวเป็นรายละเอียดการใช้งานและควรเป็นสิ่งสุดท้ายที่ผู้อ่านเห็นดังนั้นจึงอยู่ในส่วนล่างของไฟล์ ฉันเห็นด้วยกับความคิดเห็นข้างต้นว่าสิ่งนี้ใช้ไม่ได้กับไฟล์ขนาดใหญ่ นี่ไม่ควรเป็นคำตอบที่ยอมรับมีคำแนะนำที่ดีกว่าในหน้านี้
Luke Cowell

58

นอกจากนี้ยังมีตัวเลือกที่จะprivateนำหน้านิยามวิธีการตั้งแต่ Ruby 2.1

class Example

 def xmethod
 end

 private def ymethod
 end

 private def zmethod 
 end

end

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


5
คุณควรเพิ่มหมายเหตุว่าสิ่งนี้มีอยู่ใน Ruby 2.1 ซึ่งวิธีการส่งคืนคีย์ด้วยชื่อของตัวเอง: bugs.ruby-lang.org/issues/3753
konole

ฉันเชื่อว่า private สามารถใช้เป็นบล็อกได้หรือที่เรียกว่าการปิด private method บางอย่างใน private
start

ดูคำตอบของ @devpuppy ที่นี่สำหรับหมายเหตุเกี่ยวกับการทำสิ่งนี้ด้วยวิธีคลาส
manroe

การเพิ่มprivateเพียงครั้งเดียวก่อนหน้าymethodนี้ก็ใช้ได้เช่นกัน ไม่จำเป็นต้องเพิ่มหลายครั้ง
Iulian Onofrei

@IulianOnofrei หากคุณมีวิธีอื่นด้านล่างzmethodโดยไม่privateใช้วิธีนี้จะไม่เป็นส่วนตัว ดังนั้นคุณต้องทำซ้ำ (อย่างน้อยก็ด้วย Ruby 2.3)
tsauerwein

52

ดังที่คนอื่น ๆ ได้ชี้ให้เห็นแล้วว่าการประชุมนี้คือการวางระเบียบวิธีส่วนตัวไว้ที่ด้านล่างภายใต้ชั้นเรียนส่วนตัวเดียว อย่างไรก็ตามคุณควรทราบด้วยว่าโปรแกรมเมอร์หลายคนใช้วิธีการเยื้องสองครั้ง (4 ช่องว่างแทน 2) เหตุผลก็คือบ่อยครั้งที่คุณไม่เห็น "ส่วนตัว" ในโปรแกรมแก้ไขข้อความของคุณและถือว่าอาจเป็นแบบสาธารณะ ดูภาพประกอบด้านล่าง:

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

    def some_private_method
    end

    def another_private method
    end

end

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


4
นี่เป็นความโกรธทั้งหมดเมื่อฉันแสดงความคิดเห็นนี้ในปี '12 ฉันไม่เห็นสิ่งนี้บ่อยนักอีกต่อไปและมันก็ไม่เป็นที่โปรดปราน
Noah Clark

เอกชนยังสามารถจัดรูปแบบภายในหลังขวาbegin..end privateจากนั้นตัวแก้ไขสามารถตั้งค่าการเยื้องได้โดยอัตโนมัติเนื่องจากโค้ดภายในbeginis (ในตัวอย่างด้านบน) เยื้องตามความหมายด้วยช่องว่าง 4 ช่อง
Petrus Repo

ฉันทำตามแนวทางเดียวกัน ... ก่อนpublicแล้วprivate
Rahul Goyal

1
ฉันไม่เคยเห็นสิ่งนี้มาก่อนและฉันทำงานร่วมกับ Ruby มาตั้งแต่ปี 2550 โดยทั่วไปฉันไม่อยากแนะนำ
Marnen Laibow-Koser

15

ฉันคิดว่าวิธีการสาธารณะเป็นอินเทอร์เฟซบางประเภทของออบเจ็กต์และมีเหตุผลที่จะวางไว้บนตำแหน่งที่โดดเด่นที่สุดเช่นที่ด้านบนของไฟล์


5
ใช่วางวิธีการสาธารณะที่คุณน่าจะพบมากที่สุดโดยทั่วไปจะอยู่ใกล้กับด้านบนของไฟล์และสิ่งที่คุณไม่ควรมองหาควรฝังไว้ใกล้ด้านล่าง เช่นเดียวกับบทความในหนังสือพิมพ์ให้ใส่สิ่งที่สำคัญที่สุดเป็นอันดับแรก
tadman

14

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

class FooBar

  def some_public_method
  end

  def another_public_method
  end

private

  def some_private_method
  end

  def another_private method
  end

end

โปรดอ่านคำถามของฉันอีกครั้ง แก้ไขให้เฉพาะเจาะจงมากขึ้น
ZX12R

1
มันเป็นเรื่องธรรมดายิ่งกว่าอะไรทั้งหมด สิ่งที่คุณทำนั้นถูกต้องและถ้ามันสมเหตุสมผลกับคุณมากขึ้นคุณก็ควรยึดติดกับมัน ฉันพบว่าการประชุมใหญ่สามารถอ่านได้มากขึ้น แต่นั่นอาจเป็นเพราะนั่นเป็นวิธีที่ฉันถูกสอนให้เขียนดังนั้นฉันจึงคุ้นเคยกับมัน
Kyle Decot

การประกาศวิธีการเป็น "สาธารณะ" หมายความว่าอย่างไร / ทำอย่างไร
ZX12R

6

ฉันมาจากพื้นหลัง java และฉันเกลียดที่จะต้องเลื่อนเพื่อดูประเภทวิธีการ ฉันคิดว่ามันเป็นเรื่องบ้ามากที่ไม่สามารถระบุการเปิดเผยวิธีการต่อวิธีการโดยปราศจากความอัปลักษณ์ ดังนั้นผมจึงจบลงด้วยการใส่ความคิดเห็นก่อนที่แต่ละวิธีดูดแล้วประกาศ#privateprivate :...


1
และทับทิมล่าสุดก็สามารถทำได้private def method...ดีกว่า
akostadinov

5

ฉันไม่ชอบให้ระบุ public หรือ private สำหรับแต่ละวิธี การใส่วิธีการส่วนตัวทั้งหมดไว้ที่ด้านล่างทำให้ฉันมี "ส่วนตัว" เพียงอินสแตนซ์เดียวต่อไฟล์ ฉันเดาว่ามันเป็นเรื่องของรสนิยม


5

รูปแบบหนึ่งคือการใช้วิธีการของกลุ่มด้วยกันเพื่อที่คุณจะใช้privateและprotectedครั้งเดียวต่อระดับที่มากที่สุด อีกลักษณะหนึ่งคือการระบุการมองเห็นทันทีหลังจากนิยามวิธีการ:

class Example
  def my_private_method
  end
  private :my_private_method

  def my_public_method
  end
end

เมื่อ Ruby 2.1.0 defส่งคืนชื่อเมธอดเป็นสัญลักษณ์ดังนั้นรูปแบบที่คล่องตัวมากขึ้นจึงเป็นไปได้:

class Example
  private def my_private_method
  end

  def my_public_method
  end

  protected def my_protected_method
  end

  private_class_method def self.my_private_class_method
  end
end

(โปรดทราบว่าเราใช้private_class_methodสำหรับวิธีคลาส - มิฉะนั้นเราจะได้รับNameError: undefined methodตั้งแต่นั้นมาprivateคาดว่าจะมีวิธีการอินสแตนซ์แม้ว่าจะใช้เป็นมาโครเหมือนในตัวอย่างดั้งเดิม แต่ก็มีผลต่อการมองเห็นวิธีการอินสแตนซ์เท่านั้น)

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

สำหรับไวยากรณ์เมธอดคลาสคุณสามารถจัดการได้ด้วยวิธีนี้แทน:

class Example
  private def my_private_method
  end

  class << self
    private def my_private_class_method
    end
  end
end

นี่เป็นที่เดียวที่ฉันเคยเห็นการกล่าวถึง private_class_methodโทรมาก่อนและส่วนสุดท้ายเกี่ยวกับการใช้class << selfบล็อกเพื่อหลีกเลี่ยงไม่ให้ต้องใช้มันเป็นเคล็ดลับที่ดี จนถึงตอนนี้ฉันไม่รู้ว่าเมธอดคลาส "nornal" (ประกาศด้วยdef self.foo; endแทนที่จะclass << self; def foo; endไม่ได้รับผลกระทบจากตัวprivateระบุ
manroe

3

เดนนิสมีคำตอบที่สมบูรณ์แบบนั่นคือเมื่อใช้ทับทิม> = 2.1 เพียงแค่นำหน้า def ด้วย private (หรือได้รับการป้องกันสาธารณะ)

แต่ฉันเชื่อว่าตอนนี้ยังสามารถใช้ private เป็นบล็อกได้ใน:

private begin
   def foo
   end
   def bar
   end
end

def zip
end

0

โดยทั่วไปฉันจะสั่งวิธีการของฉันดังนี้:

  1. ตัวสร้าง
  2. วิธีการสาธารณะอื่น ๆ ตามลำดับตัวอักษร
  3. privateเขียนเพียงครั้งเดียว
  4. วิธีการส่วนตัวตามลำดับตัวอักษร

ฉันใช้คุณสมบัติ“ go to definition” ในโปรแกรมแก้ไขเพื่อที่จะไม่ต้องใช้การเลื่อนมากนักและในกรณีใด ๆ ถ้าชั้นเรียนใหญ่พอที่จะทำให้การเลื่อนกลายเป็นปัญหาได้ก็ควรแบ่งออกเป็นหลายชั้น


ฉันควรพูดถึงว่าฉันมักจะใส่วิธีการแปลง (เช่นto_s) ไว้ใกล้ส่วนท้ายของส่วนสาธารณะ
Marnen Laibow-Koser
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.