Как работает этот метод создания метода частного класса:
class Person
def self.get_name
persons_name
end
class << self
private
def persons_name
"Sam"
end
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"
Но это не так:
class Person
def self.get_name
persons_name
end
private
def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
ruby
access-specifier
99miles
источник
источник
Ответы:
private
похоже, не работает, если вы определяете метод для явного объекта (в вашем случаеself
). Вы можете использоватьprivate_class_method
для определения методов класса как частные (или как вы описали).В качестве альтернативы (в ruby 2.1+), поскольку определение метода возвращает символ имени метода, вы также можете использовать это следующим образом:
источник
ExiRe написал:
Может быть, это сбивает с толку, может быть и разочаровывает, но определенно не противно.
Это имеет смысл, если вы понимаете объектную модель Ruby и соответствующий поток поиска метода , особенно если принять во внимание, что
private
это НЕ модификатор доступа / видимости, а фактически вызов метода (с классом в качестве получателя), как обсуждалось здесь ... в Ruby нет такой вещи, как "приватная секция" .Чтобы определить частные методы экземпляра , вы вызываете
private
класс экземпляра, чтобы установить видимость по умолчанию для впоследствии определенных методов как частную ... и, следовательно, имеет смысл определять методы частного класса , вызываяprivate
класс класса, т.е. его метакласс.Другие основные, самопровозглашенные ОО-языки могут дать вам менее запутанный синтаксис, но вы определенно поменяете его на запутанную и менее непротиворечивую (несовместимую?) Объектную модель без возможности средств метапрограммирования Ruby.
источник
private_class_method :method_name
вы могли бы сделатьprivate_class_method def method_name...
.send(private_method)
также доступен за пределами объекта.private_class_method def self.method_name
По умолчанию все методы класса являются публичными. Чтобы сделать их приватными, вы можете использовать Module # private_class_method, как написало @tjwallace, или определить их по-другому, как вы это сделали:
class << self
открывает одноэлементный класс self, так что методы могут быть переопределены для текущего объекта self. Это используется для определения метода класса / модуля («статического»). Только там, определение частных методов действительно дает вам методы частного класса.источник
Для полноты картины мы также можем избежать объявления private_class_method отдельной строкой. Лично мне не нравится это использование, но приятно знать, что оно существует.
источник
Я также считаю, что Ruby (или, по крайней мере, мои знания об этом) не достигли цели в этой области. Например, следующее делает то, что я хочу, но неуклюже,
Мои проблемы с приведенным выше кодом состоят в том, что требования к синтаксису Ruby и мои показатели качества кода соответствуют принятым для громоздкого кода. Чтобы код работал так, как я хочу, и для того, чтобы успокоить метрики, я должен сделать сравнение () методом класса. Поскольку я не хочу, чтобы он был частью класса public API, мне нужно, чтобы он был закрытым, но сам по себе private не работает. Вместо этого я вынужден использовать «private_class_method» или какой-то такой обходной путь. Это, в свою очередь, заставляет использовать «self.class.send (: compare ...» для каждой переменной, которую я проверяю в «== ()». Теперь это немного громоздко.
источник
Методы экземпляра определяются внутри блока определения класса. Методы класса определяются как одноэлементные методы для одноэлементного класса класса, также неофициально известного как «метакласс» или «собственный класс».
private
это не ключевое слово, а метод ( Module # private ).Это вызов метода
self#private
/,A#private
который «включает» частный доступ для всех последующих определений методов экземпляра, пока не переключится иначе:Как отмечалось ранее, методы класса - это действительно одноэлементные методы, определенные в одноэлементном классе.
Или используя специальный синтаксис, чтобы открыть тело определения анонимного одноэлементного класса A:
Получатель «сообщения приватного» - self- inside
class A
- это объект класса A. self внутриclass << A
блока - это другой объект, синглтон-класс.В следующем примере в действительности вызывается два разных метода, называемых private , с использованием двух разных получателей или целей для вызова. В первой части мы определяем метод частного экземпляра («в классе A»), во второй мы определяем метод частного класса (фактически это одноэлементный метод в объекте класса singleton класса A).
Теперь немного перепишем этот пример:
Вы видите ошибку [которую сделали дизайнеры языка Ruby]? Вы переключаетесь на закрытый доступ для всех будущих методов экземпляра A, но приступаете к объявлению одноэлементного метода в другом классе, одноэлементном классе.
источник
Рубин, кажется, предлагает плохое решение. Чтобы объяснить, начните с простого примера C ++, который показывает доступ к методам частного класса:
Запуск выше
Теперь, похоже, Ruby не предоставляет эквивалент. Правила Руби, я думаю, таковы, что частные методы не должны быть доступны с получателем. То есть,
Это нормально для методов частного экземпляра, но вызывает проблемы с методами частного класса.
Я бы хотел, чтобы Ruby функционировал следующим образом:
Но, увы, вышесказанное не работает. Кто-нибудь знает лучший способ?
Когда я вижу «send» перед методом, это явный признак того, что код нарушает намерения разработчика API, но в этом случае дизайн специально должен иметь метод экземпляра класса, вызывающий метод private класса.
источник
На рубине 2.3.0
источник
private def self.second_method
перед каждой записью метода, которая не работала на моем Ruby 2.3.3. Но эта запись работает для меня.Check.second_method
также будет работать без проблем, поэтому он не является частным.private_class_method :second_method