fabOnReact
fabOnReact

Reputation: 5942

Ruby - Using Mixins to get a Parent Variable calculated in a Module

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)

Upvotes: 0

Views: 337

Answers (2)

Chowlett
Chowlett

Reputation: 46667

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

Upvotes: 1

Jagdeep Singh
Jagdeep Singh

Reputation: 4920

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.

Upvotes: 1

Related Questions