0

Thanks a lot for your help. I have a Parent, a Child and a Module in two separate files. player_fabrizio is the Instance of the Player class, which is child of Settings. The instance player_fabrizio needs to use the @totalmoney variable of the instance new_settings.

require_relative "modules_test"

class Settings
    include Variables
    attr_reader :totalmoney
end

class Player < Settings
    def initialize(kingdom, king)
        @playerData = [kingdom, king]
    end
    def calculate
        print @totalmoney
    end
end

new_settings = Settings.new
new_settings.globalSettings(100, 2)

player_fabrizio = Player.new("MyDinasty", "Fabrizio")
player_fabrizio.calculate                # no output

This is the file modules_test.rb. new_setting uses the method globalSettings of the module Variables to set the @totalmoney variable.

module Variables
    def globalSettings(totalmoney, nplayer)
        @totalmoney = totalmoney
        return @totalmoney
    end
end

The result of the method player_fabrizio.calculate should be 100, but instead no output is give. I searched the forum, but I was not able to find a question. I read a question that had a similar issue, but I was not able to find an answer.

Thanks a lot for you help Fabrizio

(Ruby, mixin instance variables and methods)

Community
  • 1
  • 1
Fabrizio Bertoglio
  • 5,890
  • 4
  • 16
  • 57
  • 1
    you are not trying to fetch a variable from parent class here. Instead you are trying to fetch it from some other object of the parent class – Jagdeep Singh Dec 14 '16 at 11:24
  • `@total_money` will be stored in the instantiated object and not in the class itself. `new_settings` is a instance of `Settings` class while `player_fabrizio`is an instance of the `Player` class that is not aware of the `new_settings` object. – lcguida Dec 14 '16 at 11:29
  • @lcguida yes, the concept of `instance` and `class` variable was not clear to me at that time, but it was even less clear to me how to easily retrieve the object instances and pass it to another object. Thanks – Fabrizio Bertoglio May 11 '19 at 10:43

2 Answers2

1

I would rename Settings to Game and do it as follows (though you are free to use whatever name suits you):

class Game
  include Variables
  attr_reader :totalmoney
end

class Player
  attr_reader :game

  def initialize(game, kingdom, king)
    @game = game
    @playerData = [kingdom, king]
  end

  def calculate
    print game.totalmoney
    # rest of the logic here
  end
end

game = Game.new
game.globalSettings(100, 2)

player_fabrizio = Player.new(game, "MyDinasty", "Fabrizio")
player_fabrizio.calculate

Let me know if it helps.

Jagdeep Singh
  • 4,880
  • 2
  • 17
  • 22
  • @Chowlett's solution looks good too. It will work (and is better solution) if you have global settings for all the players you will be creating. Instead if you can create multiple games with different settings, then you could use this one. – Jagdeep Singh Dec 14 '16 at 11:36
  • Thank to everyone for the amazing help. I could not understand this alone. Regards Fabrizio – Fabrizio Bertoglio Dec 14 '16 at 15:02
  • Thanks for the great explanation to my first question on StackOverflow, it helped me better understand the concepts of Object Oriented Programming. It was hard for me to understand abstract concepts, but these comments and answers made it very clear! I learn from this question to avoid too much abstraction in programming. – Fabrizio Bertoglio May 11 '19 at 10:46
1

Short answer - you're setting @totalmoney, which is an instance member variable of new_settings, so player_fabrizio has no access to it. You probably want to set a class member variable of Settings.

In more detail - the module is a bit of a side issue here. By including Variables into Settings, you are effectively pasting the code of Variables into Settings. So what you have is equivalent to this:

class Settings        
    attr_reader :totalmoney

    def globalSettings(totalmoney, nplayer)
        @totalmoney = totalmoney
        return @totalmoney
    end
end

class Player < Settings
    def initialize(kingdom, king)
        @playerData = [kingdom, king]
    end
    def calculate
        print @totalmoney
    end
end

new_settings = Settings.new
new_settings.globalSettings(100, 2)

player_fabrizio = Player.new("MyDinasty", "Fabrizio")
player_fabrizio.calculate                # no output

By the end of this, you have a Settings object called new_settings, with @totalmoney set to 100; and you have a Player object (which is also a Settings) named player_fabrizio, which doesn't have @totalmoney set at all.

What you may want is the following:

class Settings        
    def self.globalSettings(totalmoney, nplayer)
        @@totalmoney = totalmoney
    end
end

class Player < Settings
    def initialize(kingdom, king)
        @playerData = [kingdom, king]
    end
    def calculate
        print @@totalmoney
    end
end

Settings.globalSettings(100, 2)

player_fabrizio = Player.new("MyDinasty", "Fabrizio")
player_fabrizio.calculate

Note the @@ in front of @@totalmoney, denoting it as a class member. I've also made globalsettings a class method, so you don't need a Settings object in hand to change the global settings.

To be honest, though, I'm a bit dubious about inheriting Player from Settings - a player is not a special type of settings! Personally, I'd probably do something more like:

class Settings
    def self.globalSettings(totalmoney, nplayer)
        @@totalmoney = totalmoney
    end

    def self.totalmoney
      @@totalmoney
    end
end

class Player
    def initialize(kingdom, king)
        @playerData = [kingdom, king]
    end
    def calculate
        print Settings.totalmoney
    end
end

Settings.globalSettings(100, 2)

player_fabrizio = Player.new("MyDinasty", "Fabrizio")
player_fabrizio.calculate
Chowlett
  • 45,935
  • 20
  • 116
  • 150
  • Thanks for your answer to my first StackOverflow question, in December 2016 I just started learning Ruby and It was very hard to understand the concepts of Object Oriented Programming. Thanks! – Fabrizio Bertoglio May 11 '19 at 10:40