Maxwell Evans
Maxwell Evans

Reputation: 137

Passing parent class initialized variables to an instance of a child class

(working in Ruby) First off, I apologize in advance. I'm not a programmer by training, I've simply come to it by dint of convenience and a changing world. What I needed to do involved programming, and I got tired of waiting around for others to do my programming for me. As such, I've missed some basic concepts along the way, and when I ask these questions I sometimes make a fool of myself by consequence.

Let's say I want to define a species/job relationship in classes. I want to define a superclass "BlackAnt" and have subclasses "Worker" "Fighter" and "Queen"

To me, intuitively, this looks something like this:

class BlackAnt
  @legs = 6
end

class Worker < BlackAnt
  @jaws = 'small'
end

but if I then try

ant1 = Worker.new
puts ant1.legs

I get an error. If I amend class BlackAnt to:

class BlackAnt
  attr_accessor :legs
  @legs = 6
end

ant1.legs returns 'nil'

I've tried the method outlined here: http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

and this allows Worker.legs to return '6', but... alas:

ant1 = Worker.new
Worker.legs => '6'
ant1.legs => 'nil'

At a guess, the values of those parent variables are not being initialized each time a new child is spawned.

I feel I'm being silly about this somehow, and the reply is no doubt going to make me curse the day I discovered caffeine-driven all-nighters. What I need to do is arrange things so that I can create objects like so:

ant1 = Worker.new
ant2 = Queen.new
ant3 = Fighter.new

and have them each acquire the appropriate quantity of legs, along with whatever special characteristics were assigned in the child class. The worker/queen/fighter classifications will be bound by namespaces such that the actual calls will be:

ant1 = AntBlack::Worker.new
ant2 = AntRed::Worker.new
ant3 = AntRed::Queen.new

etc.

I'd like to then be able to check the quantity of legs of an individual ant using:

ant1.legs #=> 6

I may be going around my elbow to get to my thumb. If so, feel free to offer alternate suggestions for ways to achieve the same result, I will greatly appreciate the insights.

///updated re:response///

class AntRed
  attr_accessor :legs
  def initialize
    @legs = 6
  end
end

class Worker < AntRed
  @strength = 1
end

result:

irb(main):009:0> ant1 = Worker.new
#=> #<Worker:0x87616ac @strength=1>
irb(main):010:0> ant1.legs
#=> nil

Upvotes: 3

Views: 5155

Answers (3)

user1933562
user1933562

Reputation: 26

you mean you want a class's instance varieble which has been initialed!

so you can do it like this:

class BlackAnt
  attr_accessor :legs
  @legs = 6

  def initialize
    @legs = self.class.instance_variable_get(:@legs)
  end
end

newObj = BlackAnt.new
newObj.legs

Upvotes: 0

BernardK
BernardK

Reputation: 3734

At a guess, the values of those parent variables are not being initialized each time a new child is spawned.

In Ruby instance variables belong to a single object. Look at point 7) in my answer starting

To address your "If true that they are variables"

in Why are symbols in Ruby not thought of as a type of variable?


I don't understand why you get irb(main):010:0> ant1.legs #=> nil. For me it works (at least as script).

class AntRed
  attr_accessor :legs
  def initialize
    @legs = 6
  end
end

class Worker < AntRed
end

ant1 = Worker.new
print 'ant1.legs : '; puts ant1.legs

Execution :

$ ruby -w test.rb 
ant1.legs : 6

Upvotes: 0

cbascom
cbascom

Reputation: 766

Define your BlackAnt class as follows:

class BlackAnt
  attr_accessor :legs

  def initialize
    @legs = 6
  end
end

And your Worker class as follows:

class Worker < BlackAnt
  attr_accessor :strength

  def initialize
    super

    @strength = 1
  end
end

The way you currently define the BlackAnt class, you are storing legs as a class level instance variable.

Upvotes: 5

Related Questions