Reputation: 2123
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!
Upvotes: 3
Views: 10830
Reputation: 48589
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.
Upvotes: 6
Reputation: 2869
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
Upvotes: 4