# Composition (Dragon "has a" Trait)

**URL:** <https://www.ruby-forum.com/t/composition-dragon-has-a-trait/119836>\
**Category:** Ruby\
**Created:** [November 11, 2007, 4:31am UTC](https://www.ruby-forum.com/t/composition-dragon-has-a-trait/119836 "2007-11-11T04:31:18Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thufir](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ee7513/32.png) [@Thufir](https://www.ruby-forum.com/u/Thufir)\
**Post date:** [November 11, 2007, 4:31am UTC](https://www.ruby-forum.com/t/composition-dragon-has-a-trait/119836/1 "2007-11-11T04:31:18Z")

</div>

I want to put all of the current attr\_accessor’s  
(:life, :strength, :charisma, :weapon) into class Traits so that each  
Creature instance will have one Traits object to go along with that  
class.

by themselves, Traits, Dragon and Class give no error messages from  
ruby. From using the IRB it’s clear that it’s line 6 of the Dragon  
class:

@traits.life = 1340

C:\code\creat3\>  
C:\code\creat3\>  
C:\code\creat3\>creatures.rb  
./Dragon.rb:6:in `initialize': undefined method`life=’ for  
nil:NilClass (NoMeth  
odError)  
from C:/code/creat3/creatures.rb:12:in `new' from C:/code/creat3/creatures.rb:12 from C:/code/creat3/creatures.rb:10:in`times’  
from C:/code/creat3/creatures.rb:10

C:\code\creat3\>  
C:\code\creat3\>  
C:\code\creat3\>type creatures.rb  
require ‘ArrayOfCreatures’  
require ‘MakeCreature’  
require ‘Location’

include MakeCreature

NumOfCreatures=3  
creatures = ArrayOfCreatures.instance

NumOfCreatures.times do |i|

# creatures[i]=MakeCreature.randomCreature

```
    creatures[i]=Dragon.new

```

end

creatures.length.times do |i|  
number = Kernel.rand(6)  
creatures.oneElementToString(i)  
print “factorial of\t”  
print number  
print “\tis\t”  
print Math.factorial(number)  
end

C:\code\creat3\>  
C:\code\creat3\>  
C:\code\creat3\>type Creature.rb  
require ‘Math’  
require ‘Traits’

class Creature

Creature.extend Math  
include Math

def initialize ()  
@location = Room.new  
@traits = Traits.new  
end

def toString ()  
print “class\t\t”  
print self.class

```
    @attributes.toString

    print "\n"

```

end

end

C:\code\creat3\>  
C:\code\creat3\>type Dragon.rb  
require ‘Creature’

class Dragon \< Creature

def initialize ()  
@traits.life = 1340  
end

end

C:\code\creat3\>  
C:\code\creat3\>

thanks,

Thufir

---

<div class="post-metadata">

**Author:** ![Thufir](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ee7513/32.png) [@Thufir](https://www.ruby-forum.com/u/Thufir)\
**Post date:** [November 11, 2007, 4:45am UTC](https://www.ruby-forum.com/t/composition-dragon-has-a-trait/119836/2 "2007-11-11T04:45:21Z")

</div>

Thufir wrote:

> C:\code\creat3\>type Creature.rb  
> class Creature  
> …  
> def initialize ()  
> @location = Room.new  
> @traits = Traits.new  
> end  
> …  
> end  
> …  
> class Dragon \< Creature  
> def initialize ()  
> @traits.life = 1340  
> end  
> end

It seems you think that the initialize of Creature gets called because  
Dragon is a subclass of it. This is not the case. For example:

irb(main):001:0\> class Foo  
irb(main):002:1\> def initialize  
irb(main):003:2\> p “Foo.initialize”  
irb(main):004:2\> end  
irb(main):005:1\> end  
=\> nil  
irb(main):006:0\> Foo.new  
“Foo.initialize”

irb(main):007:0\> class Bar \< Foo  
irb(main):008:1\> def initialize  
irb(main):009:2\> p “Bar.initialize”  
irb(main):010:2\> end  
irb(main):011:1\> end  
=\> nil  
irb(main):012:0\> Bar.new  
“Bar.initialize”

If you want the initialize method from a superclass to be called, you  
need to explicitly do so, and decide when to do it. For example:

irb(main):019:0\> class Bar2 \< Foo  
irb(main):020:1\> def initialize  
irb(main):021:2\> super # call this first  
irb(main):022:2\> p “Bar2.initialize”  
irb(main):023:2\> end  
irb(main):024:1\> end  
=\> nil  
irb(main):025:0\> Bar2.new  
“Foo.initialize”  
“Bar2.initialize”

Though it doesn’t make a difference in my above simple example, note  
that calling “super” without any parentheses automatically passes in  
any arguments passed to the initialize function. This is convenient,  
but can be a problem if your superclass’s initialize method expects  
different arguments than the subclass’s.

---

<div class="post-metadata">

**Author:** ![Thufir](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/ee7513/32.png) [@Thufir](https://www.ruby-forum.com/u/Thufir)\
**Post date:** [November 13, 2007, 7:05am UTC](https://www.ruby-forum.com/t/composition-dragon-has-a-trait/119836/3 "2007-11-13T07:05:28Z")

</div>

Oh, thanks for pointing out how to ensure that the initialize  
(constructor) method is called.

-Thufir
