Каковы различия между "частными", "публичными" и "защищенными методами"?
Я изучаю Ruby и дошел до того, что запутался.
Книга, которую я использую, говорит о private
, public
, а также protected methods
, но я все еще немного смущен. Каковы различия между каждым?
7 ответов
Публичный - можно звонить откуда угодно
Private - метод не может быть вызван вне области видимости класса. Объект может отправить сообщение только себе
пример: пекарь имеет bake
метод как публичный, но break_eggs
является частным
Защищенный - Вы можете вызывать защищенные методы объекта, если он является объектом по умолчанию self
является экземпляром того же класса, что и объект, метод которого вы вызываете
пример: с n
защищенный метод, c1
можно спросить c2
выполнить c2.n
, так как c1
а также c2
оба экземпляра одного и того же класса
И последнее но не менее важное:
- Наследование. Подклассы наследуют правила доступа к методам своего суперкласса.
если "класс D ссылка: http://www.amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699
public
методы открыты для всех. Что касается private
против protected
Я имею в виду " частные методы Ruby против защищенных методов":
В чем разница между частными и защищенными методами в Ruby? В Ruby основное различие между "закрытым" и "защищенным" методом заключается в том, что закрытый метод не может быть вызван с явным получателем, в то время как защищенный метод может. Вы спрашиваете, что такое "явный получатель"? Явный получатель - это объект, который получает сообщение. В следующем примере у нас есть получатель ('parent') и метод ('get_name'). "Родительский" объект получает инструкцию для выполнения метода "get_name".
Разница будет в видимости и о том, как на них влияет наследование:
Видимость:
|| Везде || Публичный доступ может быть получен изнутри и снаружи класса.
|| Внутри класса || Доступ к личным и защищенным доступам возможен только из класса.
Сходство между Защищенным и Частным:
- Оба могут быть доступны извне класса через публичный метод.
Различия между защищенным и частным:
Закрытый метод не может быть вызван с получателем (даже с #self). ЕСЛИ... вызов метода ЧАСТНОГО УСТАНОВКИ. Если вы попытаетесь удалить получателя, 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
Проверьте " Программирование Ruby / Синтаксис / Классы" для подробного примера и объяснения.
Проще говоря, различия между private
, public
, а также protected
методы - это видимость этого метода в программе, вроде только для чтения, чтения и записи и почти невидимые.
В отличие от некоторых других языков, вы не можете полностью скрыть закрытый метод Ruby, вы можете получить доступ только к закрытым методам для вашего экземпляра объекта, а не для любого другого экземпляра объекта класса.
Публичная, конечно, полная доступность, и методы, как правило, по умолчанию являются публичными, за некоторыми исключениями.
Защищенные методы доступны из объектов того же класса или даже потомков, что не относится к частным методам.
Позволь мне объяснитьPrivate
а также protected
методы работают немного по-другому в Ruby
чем в большинстве других языков программирования. Предположим, у вас есть класс с именем Foo
и подкласс SubFoo
, На таких языках, как Java
, SubFoo
не имеет доступа ни к каким частным методам, определенным Foo . Как видно из Решения, Ruby не позволяет скрыть методы класса от его подклассов. В этом случае, Ruby
частные работы вроде Java
"s protected
,
Предположим далее, что у вас есть два экземпляра класса Foo, a
а также b
, На таких языках, как Java
, a
а также b
могут звонить друг другу private methods
, В Ruby
, вам нужно использовать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
Я думаю, что сломать явный получатель - вот что важно, если у вас возникли проблемы с пониманием концепции.
Явный получатель - это объект, который принимает сообщение.
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.
Когда метод является закрытым, он может использоваться только другими методами внутри объекта, в классе которого он определен.
Изучая информацию, которую я взял отсюда, я расширил объяснения из-за ошибок и, на мой взгляд, помогает понять, почему и как использовать защищенные, а не частные.
1) Защищено:
Строка с номером 12 вылетает, потому что полученный параметр получен из другого класса, сообщение об ошибке ясно:
v.rb:12:in `==': undefined method `sku' for "Object of another class ==> crash":String (NoMethodError)
2) Частный:
Если удалить себя из строк 8 и 12, и я изменил защищенный для частного, сбой, потому что в строке 12, другие не знают, что такое 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"