web-dev-qa-db-ja.com

「プライベート」、「パブリック」、「保護されたメソッド」の違いは何ですか?

Rubyを学んでいて、混乱するところまで来ました。

私が使用している本はprivatepublic、およびprotected methodsについて話していますが、それでも少し混乱しています。それぞれの違いは何ですか?

39
Billjk

Public-どこからでも呼び出すことができます

Private-メソッドをクラススコープ外で呼び出すことはできません。オブジェクトはそれ自体にのみメッセージを送信できます

例:パン屋はbakeメソッドをパブリックとして持っていますがbreak_eggsは非公開です

Protected-デフォルトのオブジェクトselfがそのオブジェクトと同じクラスのインスタンスである限り、オブジェクトの保護されたメソッドを呼び出すことができますあなたが呼んでいるメソッド

例:n保護されたメソッド、c1c2を実行するにはc2.n、なぜならc1およびc2は両方とも同じクラスのインスタンスです

そして最後に重要なことですが:

  • 継承:サブクラスはスーパークラスのメソッドアクセスルールを継承します

「クラスD <C」の場合、DはCのインスタンスと同じアクセス動作を示します

参照: http://www.Amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699

40
Julio Marins

publicメソッドは誰でも利用できます。 privateprotectedについては、「 Rubyプライベートメソッドと保護されたメソッド 」を参照しています。

Rubyの「プライベート」メソッドと「保護」メソッドの違いは何ですか? Rubyでは、「プライベート」メソッドと「保護」メソッドの主な違いは、プライベートメソッドを明示的なレシーバーで呼び出すことはできませんが、保護されたメソッドはできることです。 「明示的な受信者」とは何ですか?明示的な受信者は、メッセージを受信するオブジェクトです。次の例では、レシーバー( 'parent')とメソッド( 'get_name')があります。 「親」オブジェクトが「get_name」メソッドを実行するための命令を受け取っています。

31
ScottJShea

詳細な例と説明については、「 Rubyプログラミング/構文/クラス 」を確認してください。

簡単に言えば、privatepublic、およびprotectedメソッドの違いは、プログラム内でのそのメソッドの可視性であり、読み取り専用、読み取りおよび書き込みのようなもので、ほとんど見えません。 。

他の一部の言語とは異なり、Rubyプライベートメソッドを完全に非表示にすることはできません。オブジェクトのインスタンスのプライベートメソッドにのみアクセスでき、クラスの他のオブジェクトインスタンスにはアクセスできません。

もちろんパブリックは完全なアクセシビリティであり、メソッドは通常いくつかの例外を除いてデフォルトでパブリックに設定されています。

プロテクトメソッドには、同じクラスのオブジェクトや子からもアクセスできますが、プライベートメソッドの場合はそうではありません。

6
lifejuggler

違いはVisibilityとそれらがInheritanceによってどのように影響を受けるかです:

可視性

|| どこでも||クラスの内外からパブリックにアクセスできます。

|| クラス内|| PrivateとProtectedの両方は、クラス内からのみアクセスできます。

ProtectedとPrivateのsimilarity

  • どちらもクラスの外部からpublicメソッドを介してアクセスできます。

ProtectedとPrivateのdifferencesは次のとおりです。

  • プライベートメソッドは、レシーバーでは呼び出せません(#selfでも呼び出せません)。 [〜#〜] unless [〜#〜]...PRIVATE SETTERメソッドを呼び出す。レシーバーを削除しようとすると、Rubyはローカル変数を作成します。この場合、Selfは必須です。

  • 保護対象は自己を使用する場合と使用しない場合があります。

  • Protectedは、同じクラスの別のオブジェクトのprotectedメソッドにアクセスできますが、Privateはできません。

それがになるとき継承

  • プライベートメソッドは、サブクラスで暗黙的にのみ呼び出すことができます(単にメソッドの名前のみ)が明示的には呼び出せません(#selfを使用)。

  • Protectedは両方の方法で呼び出すことができます(#self ||の有無にかかわらず、暗黙的または明示的に)。

以下のコードの例:

 class Dog
  attr_accessor :name, :age

  def initialize(n, a)
    self.name = n
    self.age = a
  end

  def accessing_private
    "#{self.name} in human years is #{human_years}. This is secret!"
  end

  def accessing_protected
    "Will this work? " + a_protected_method
  end

  def eat_more_than(other) 
  # accessing other instance's protected method from the same class
    daily_diet < other.daily_diet 
    "#{name} eats more than #{other.name}"
  end

  def boy 
    gender_method("boy") # accessing private setter method
  end

  protected

  def daily_diet 
    age * 2 # the younger, the more they have to eat 
  end

  def a_protected_method
    "Yes, I'm protected!"
  end

  private

  attr_writer :gender

  def gender_method(gender)
    self.gender = gender # private setter method requires self
    "#{name} is a #{gender}"
  end

  def human_years
    age * 8
  end
end

# Create the first object of Dog
blake = Dog.new("Blake", 5)

p blake.accessing_private # "Blake in human years is 16. This is secret!"

p blake.accessing_protected # "Will this work? Yes, I'm protected!"

# Create the second object of Dog
jackson = Dog.new("Jackson", 1)

# Below, protected methods from different objects of the same type/class 
# are proven to share access
p jackson.eat_more_than(blake) # true -> "Jackson eats more than Blake"

# Below, accessing private setter method through a public method.
p blake.boy # Blake is a boy 
5
Maya Novarini

Privateメソッドとprotectedメソッドの動作について、Rubyと他のほとんどのプログラミング言語では少し異なります。 FooというクラスとSubFooというサブクラスがあるとします。 Javaなどの言語では、SubFooはFooで定義されたプライベートメソッドにアクセスできません。ソリューションに見られるように、Rubyは、クラスのメソッドをサブクラスから隠す方法を提供しません。このように、Rubyのプライベートは、Javaprotectedのように機能します。

さらに、Fooクラスの2つのインスタンス、abがあるとします。 Javaabなどの言語では、お互いのprivate methodsを呼び出すことができます。 Rubyでは、そのためにprotected methodを使用する必要があります。これは、privateprotectedメソッドとRubyメソッドの主な違いです。

class Foo
  private
  def pri
    'hey I am private of Foo'
  end

  protected
  def prot
    'Hey I am protected of Foo'
  end
end

Fooのサブクラス

class SubFoo < Foo
  def call_pri_of_foo
    pri
  end

  def call_prot_of_foo
    prot
  end
end

SubFoo内のアクセサーを呼び出す

 > sub_foo = SubFoo.new
 => #<SubFoo:0x00000002b56ad8> 
 > sub_foo.call_pri_of_foo
 => "hey I am private of Foo" 
 > sub_foo.call_prot_of_foo
 => "Hey I am protected of Foo"

ここまで;違いはないようです

next_sub_foo = SubFoo.new
 => #<SubFoo:0x00000002b1a0b0>

def next_sub_foo.access_private(child_of_sub_foo)
  child_of_sub_foo.pri
end

def next_sub_foo.access_protected(child_of_sub_foo)
  child_of_sub_foo.prot
end

アクセサを呼び出しています

> next_sub_foo.access_private(sub_foo)
# => NoMethodError: private method `pri' called for #<SubFoo:0x00000002b56ad8>

しかし、兄弟の保護されたメソッドにアクセスできます

> next_sub_foo.access_protected(sub_foo)
# => "Hey I am protected of Foo"

より明確な画像については、@tenderloveのブログもご覧ください http://tenderlovemaking.com/2012/09/07/protected-methods-and-Ruby-2-0.html

5
illusionist

明示的なレシーバーを分解することは、コンセプトを理解するのに問題がある場合に重要だと思います。

明示的な受信者は、メッセージを受け入れるオブジェクトです。

 person.get_name

personはレシーバであり、メソッド「get_name」はオブジェクト「person」にメソッド「get_name」を実行するよう指示しています。

class Person
    attr_accessor :first_name, :last_name 

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
    puts "And #{phone_number}" # Private method called when initialized
  end

  private 
  def phone_number
    return "XXX-XXX-XXXX"
  end
end


p p1 = Person.new("mike", "jones")


p p1.phone_number # Not within the context of the object instance.

メソッドがプライベートの場合、そのクラスが定義されているオブジェクト内の他のメソッドでのみ使用できます。

2
gkstr1

私が得た情報 here を研究して、エラーを通して説明を拡張しました。私の意見では、非公開ではなく保護を使用する理由と方法を理解するのに役立ちます。

1)保護:

受信したパラメーターが別のクラスからのものであるため、行num 12がクラッシュし、エラーメッセージは明らかです。

v.rb:12:in `==': undefined method `sku' for "Object of another class ==> crash":String (NoMethodError)

2)プライベート:

8行目と12行目からselfを削除し、protectedを変更した場合private、12行目でクラッシュotherは何を知らないskuは:

v.rb:12:in `==': private method `sku' called for #<Product:0x00000001574e68 @name="Bread", @quantity=1> (NoMethodError)

プログラム:

class Product
  attr_accessor :name, :quantity

  def initialize(name)
    @name = name
    @quantity = 1

    puts "The SKU is #{self.sku}"
  end

  def == (other)
    self.sku == other.sku
  end

  protected
    def sku
      name.crypt("yo")
    end
end

milk1 = Product.new("Milk")
milk2 = Product.new("Milk")
bread = Product.new("Bread")

puts milk1 == bread

puts milk1 == milk2

puts milk1 == "Object of another class ==> crash"
0
Albert Català