Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby - how to handle problem of subclass accidentally overriding superclass's private fields?

Suppose you write a class Sup and I decide to extend it to Sub < Sup. Not only do I need to understand your published interface, but I also need to understand your private fields. Witness this failure:

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"

The question is, what is the right way to tackle this problem? It seems a subclass should be able to use whatever fields it wants without messing up the superclass.

EDIT: The equivalent example in Java returns "from Sup", which is the answer this should produce as well.

like image 947
Claudiu Avatar asked Mar 18 '11 13:03

Claudiu


People also ask

Can you override a private method in Ruby?

Overriding a private method Here, Child class overrides Parent#role private method. In this case we can see that role is defined as public method after this overriding. Also, private_methods does not include #role even though this method is private in the ancestor chain of Child — through Parent#role method.

How can private fields of a superclass can be accessed in a subclass?

To access the private members of the superclass you need to use setter and getter methods and call them using the subclass object.

Can a subclass override inherited methods?

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.

What are the methods that you Cannot override in a subclass?

Methods a Subclass Cannot Override Also, a subclass cannot override methods that are declared static in the superclass. In other words, a subclass cannot override a class method. See Instance and Class Members for an explanation of class methods.


2 Answers

Instance variables have nothing to do with inheritance, they are created on first usage, not by some defining mechanism, therefore there is no special access control for them in language and they can not be shadowed.

Not only do I need to understand your published interface, but I also need to understand your private fields.

Actually this is an "official" position. Excerpt from "The Ruby Programming Language" book (where Matz is one of the authors):

... this is another reason why it is only safe to extend Ruby classes when you are familiar with (and in control of) the implementation of the superclass.

If you don't know it inside and out you're on your own. Sad but true.

like image 121
hoha Avatar answered Oct 10 '22 09:10

hoha


Don't subclass it!

Use composition instead of inheritance.

Edit: Rather than MyObject subclassing ExistingObject, see if my_object having an instance variable referring to existing_object would be more appropriate.

Instance variables belong to instances (ie objects). They're not determined by the classes themselves.

like image 29
Andrew Grimm Avatar answered Oct 10 '22 09:10

Andrew Grimm