Каковы различия между «частными», «публичными» и «защищенными методами»? - PullRequest
37 голосов
/ 27 марта 2012

Я изучаю Ruby и дошел до того, что запутался.

В книге, которую я использую, говорится о private, public и protected methods, но я все еще немного сбит с толку. Каковы различия между каждым?

Ответы [ 7 ]

36 голосов
/ 05 февраля 2014

Публичный - звонить можно откуда угодно

Private - Метод не может быть вызван вне области видимости класса. Объект может отправить сообщение только себе

ex: у пекаря есть метод bake как публичный, но break_eggs является приватным

Защищено - Вы можете вызывать защищенные методы объекта, если объект по умолчанию self является экземпляром того же класса, что и объект, метод которого вы вызываете

ex: с помощью n защищенного метода c1 может попросить c2 выполнить c2.n, поскольку c1 и c2 являются экземплярами одного и того же класса

И последнее, но не менее важное:

  • Наследование : Подклассы наследуют правила доступа к методам своего суперкласса

если «класс D

ссылка: http://www.amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699

31 голосов
/ 27 марта 2012

public методы открыты для всех.Что касается private против protected, я имею в виду « частные методы Ruby против защищенных методов »:

В чем разница между «частным» и «защищенным»методы в Ruby?В Ruby основное различие между «закрытым» и «защищенным» методом заключается в том, что закрытый метод не может быть вызван с явным получателем, тогда как защищенный метод может .Вы спрашиваете, что такое «явный получатель»?Явный получатель - это объект, который получает сообщение.В следующем примере у нас есть получатель ('parent') и метод ('get_name').«Родительский» объект получает инструкцию для выполнения метода «get_name».

6 голосов
/ 27 марта 2012

Проверьте " Программирование на Ruby / Синтаксис / Классы " для подробного примера и объяснения.

Проще говоря, различия между private, public и protected методами заключаются в видимости этого метода в программе, вроде как только для чтения, чтения и записи, и почти невидимы.

В отличие от некоторых других языков, вы не можете полностью скрыть закрытый метод Ruby, вы можете получить доступ только к закрытым методам для вашего экземпляра объекта, но не для любого другого экземпляра объекта класса.

Общедоступным, конечно же, является полная доступность, а методы обычно устанавливаются по умолчанию на общедоступные с некоторыми исключениями.

Защищенные методы доступны из объектов того же класса или даже потомков, что не относится к частным методам.

5 голосов
/ 01 сентября 2017

Разница будет в Видимость и как на них влияет Наследование :

Видимость :

|| Везде || Публичный доступ может осуществляться изнутри и снаружи класса.

|| Внутри класса || Доступ к личным и защищенным доступам возможен только из класса.

Сходство между Защищенным и Частным:

  • Оба могут быть доступны извне класса через открытый метод.

Различия между защищенными и частными:

  • Частный метод не может быть вызван с получателем (даже с #self). UNLESS ... вызов метода PRIVATE SETTER . Если вы попытаетесь удалить получателя, Ruby создаст локальную переменную. Самообязательность в этом случае обязательна.

  • Защищенные могут использовать или не использовать себя.

  • Защищенный может получить доступ к защищенному методу другого объекта из того же класса, а Приватный - нет.

Когда дело доходит до Наследование :

  • Закрытые методы можно вызывать только для подклассов неявно (просто имя метода) , но не явно (используя #self).

  • Защищенные могут быть вызваны в обоих направлениях (с или без #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 голосов
/ 30 марта 2016

Позвольте мне объяснить, Private и protected методы работают немного иначе в Ruby, чем в большинстве других языков программирования.Предположим, у вас есть класс с именем Foo и подкласс SubFoo.В таких языках, как Java, SubFoo не имеет доступа к каким-либо закрытым методам, определенным Foo.Как видно из Решения, Ruby не позволяет скрыть методы класса от его подклассов.Таким образом, приват Ruby работает как Java protected.

Предположим, что у вас есть два экземпляра класса Foo, a и b.На таких языках, как Java, a и b, можно называть друг друга private methodsRuby для этого нужно использовать protected method.В этом основное отличие методов private и protected в 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

1 голос
/ 18 сентября 2016

Я думаю, что отключение явного получателя - это то, что важно, если у вас возникают проблемы с пониманием концепции.

Явный получатель - это объект, принимающий сообщение.

 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.

Когда метод является закрытым, он может использоваться только другими методами внутриобъект, в классе которого он определен.

0 голосов
/ 25 мая 2016

Изучая информацию, которую я взял с здесь , я расширил объяснения из-за ошибок и, на мой взгляд, помогает понять, почему и как использовать защищенные, а не частные.

1) Защищено:

Сбой строки № 12, поскольку полученный параметр получен из другого класса, сообщение об ошибке сбрасывается:

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

2) Частное лицо:

Если удалить self из строк 8 и 12, и я заменяю 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"
...