3

I'm trying to access a datamember of a parent class from a child class. I am not sure how to call it. I have found a lot of info about accessing class variables but not instance variables from a child class. Here is my code:

class Shape @var = "woohoo" def initialize () end def area () end end class Rectangle < Shape @length @width def initialize ( l,w ) @length = l @width = w end def area () print @var return @length * @width end end 

I get an error trying to print @var. I tried parent.@var, Shape.@var, and a number of other combinations that I'd expect from other languages. What is the correct way to print (and if possible change) that variable within an instance of the child class?

EDIT: I want individual instances of the child class to replace the 'woohoo' string with their own unique strings.

Thanks!

0

2 Answers 2

6

I'm trying to access a datamember of a parent class from a child class. I am not sure how to call it. I have found a lot of info about accessing class variables but not instance variables from a child class. Here is my code:

class Shape @var = "woohoo" 

That variable is known as a class instance variable, and the reason people use a class instance variable instead of a class variable, i.e. an @@variable, is precisely so that child classes cannot access it. Because class instance variables are the way class variables work in other languages, @@variables are not used much in ruby because their behavior is surprising if you come from another language that has class variables.

Your use case apparently calls for a class variable to be accessible in the child class, so have at it with an @@variable.

EDIT: I want individual instances of the child class to replace the 'woohoo' string with their own unique strings.

You can use class instance variables for that:

class Shape @var = "shapehoo" class <<self attr_accessor :var end def display_class_instance_var puts Shape.var end end class Rectangle < Shape @var = "recthoo" def display_class_instance_var puts Rectangle.var end end class Circle < Shape @var = "circlehoo" def display_class_instance_var puts Circle.var end end Shape.new.display_class_instance_var Rectangle.new.display_class_instance_var Circle.new.display_class_instance_var Rectangle.new.display_class_instance_var Shape.new.display_class_instance_var --output:-- shapehoo recthoo circlehoo recthoo shapehoo 

As with regular instance variables, class instance variables are private, so you have to provide accessor methods if you want to access them. The accessors need to be in the class's singleton class, which you can open using the syntax:

class <<self end 

Added:

About this code:

class Rectangle < Shape @length @width def initialize ( l,w ) @length = l @width = w end 

In your initialize() method, you are not setting the @length, @width variables you declared above the initialize method. In ruby, @variables attach themselves to whatever object is self at the time the @variables are created. Here is what your code looks like with some more detail:

class Rectangle < Shape #self=Rectangle class @length @width def initialize ( l,w ) #self=a new instance of the Rectangle class created by initialize @length = l @width = w end 

As a result, the @variables created in initialize() attach themselves to the new instance, while the @variables declared above initialize() attach themselves to the Rectangle class, which means they are completely different variables.

Sign up to request clarification or add additional context in comments.

3 Comments

why use class <<self insted of just accessor ? and why call Rectangle.var insted o self.var ord just @var ? Its just a question ;)
@Lukas Baliak, 1)why use class <<self insted of just accessor?-- Because calling attr_accessor at the class level would create accessors for an instance variable named @var--not accessor for a class instance variable named @var. 2)and why call Rectangle.var insted o self.var -- Because inside an instance method, self is equal to the instance calling the method, but the accessor method is defined on the class object, so you need to call the accessor with the class object. You could write self.class.var.
@LukasBaliak, You're welcome. I guess the op didn't want to use class variables at all anyway.
4

You can use "super" to call parent class initialize block and define instance variable "@var". In that case you can modify value of this instance variable for another instance. Like this:

class Shape def initialize () @var = "woohoo" end end class Rectangle < Shape def initialize(l, w) @length = l @width = w super() end def area() print @var return @length * @width end def var=(new_value) @var = new_value end end a = Rectangle.new(1,1) a.area # => woohoo1 a.var = "kaboom" a.area # => kaboom1 b = Rectangle.new(2,2) b.area # => woohoo4 

Or ofc you can use attr_accessor

class Shape def initialize @var = "woohoo" end end class Rectangle < Shape attr_accessor :var def initialize(l, w) @length, @width = l, w super() end def area() print @var return @length * @width end end a = Rectangle.new(1,1) a.area # => woohoo1 a.var = "kaboom" a.area # => kaboom1 b = Rectangle.new(2,2) b.area # => woohoo4 

2 Comments

and define class variable "@var" Your code does not define any class variables of any type. The important trait of instance variables is that they can have different values for each instance, while a class (instance) variable has the same value for all instances.
What if the Shape initializer has some arguments that are not present in the Rectangle initializer?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.