Ruby - как справиться с проблемой подкласса, случайно перекрывающей приватные поля суперкласса? - PullRequest
5 голосов
/ 18 марта 2011

Предположим, вы пишете класс Sup, и я решил расширить его до Sub <<code>Sup.Мне нужно понимать не только ваш опубликованный интерфейс, но и ваши личные поля.Свидетель этого отказа:

class Sup

  def initialize
    @privateField = "from sup"
  end

  def getX
    return @privateField
  end
end

class Sub < Sup

  def initialize
    super()
    @privateField = "i really hope Sup does not use this field"
  end
end

obj = Sub.new
print obj.getX #  prints "i really hope Sup does not use this field"

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

РЕДАКТИРОВАТЬ: эквивалентный пример в Java возвращает "from Sup", что является ответом, который это должно датьа также.

Ответы [ 4 ]

9 голосов
/ 18 марта 2011

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

Мне нужно понимать не только ваш опубликованный интерфейс, но и ваши личные поля.

На самом деле это "официальная" позиция.Выдержка из книги «Язык программирования Ruby» (где Мац является одним из авторов):

... это еще одна причина, по которой безопасное расширение классов Ruby возможно только тогда, когда вы знакомы с (и контролирует) реализацию суперкласса.

Если вы не знаете этого изнутри и снаружи, вы сами по себе.Печально, но это правда.

1 голос
/ 18 марта 2011

в отличие от java / C #, в ruby ​​приватные переменные всегда видны наследующим классам. Нет способа скрыть приватные переменные.

1 голос
/ 18 марта 2011

Не делайте это на подклассы!

Используйте композицию вместо наследования.

Редактировать : Вместо того, чтобы создавать подклассы MyObject для ExistingObject, посмотрите, будет ли более подходящим my_object с переменной экземпляра, ссылающейся на существующий_объект.

Переменные экземпляра принадлежат экземплярам (то есть объектам). Они не определяются самими классами.

0 голосов
/ 18 марта 2011

Ruby и Java не относятся к «частному» свойству одинаково. В Ruby, если вы помечаете что-то как личное, это означает, что это не может быть вызвано с получателем, т.е.

 class Sub
   private
   def foo; end
 end

sub.foo => error accessing private method with caller

но вы всегда можете получить к нему доступ, если вы измените, кто себя такой, как:

sub.instance_eval { foo } #instance_eval changes self to receiver, 'sub' in this example

Вывод: не надейтесь, что вы можете спрятать или защитить что-то из космоса! Или с большой силой приходит большая ответственность!

EDIT:

Да, я знаю, вопрос был для полей, но это то же самое. Вы всегда можете сделать:

sub.instance_eval { @my_private_field = 'something else' }
puts sub.instance_eval { @my_private_field }
...