Miquel
Miquel

Reputation: 23

How to create a copy constructor in Ruby

I'm new to Ruby and I'm programming a game where there is a class named Player and I'm having issues when trying to copy an object. My code looks something like this:

class Player

    attr_accessor :imprisoned
    attr_reader :name
    attr_reader :balance
    attr_accessor :freedom_card
    attr_accessor :current_box
    attr_reader :properties

    # Default constructor with no parameters
    def initialize (name = "")
        @name = name
        @imprisoned = false
        @balance = 7500
        @properties = Array.new
        @freedom_card = nil
        @current_box = nil
    end

    # Constructor with one parameter (it works)
    def self.nuevo (name)
        self.new(name)
    end

    # Copy constructor (doesn't seem to work)
    def self.copia (other_player)
        @name = other_player.name
        @imprisoned = other_player.imprisoned
        @balance = other_player.balance
        @properties = other_player.properties
        @freedom_card = other_player.freedom_card
        @current_box = other_player.current_box
        self
    end

    # ...
end

When testing it with this:

player = Player.nuevo ("John")
puts player.name
player_2 = Player.copia(player)
puts player_2.name

I get this:

John
NoMethodError: undefined method `name' for ModeloQytetet::Player:Class

What could be the error? It also fails when using other attributes or methods from the copied object but all works fine in the original one. Thanks in advance and sorry for any English mistakes (not my first language).

Upvotes: 2

Views: 1329

Answers (1)

oren
oren

Reputation: 3209

In:

def self.copia(other_player)
  @name = other_player.name
  @imprisoned = other_player.imprisoned
  @balance = other_player.balance
  @properties = other_player.properties
  @freedom_card = other_player.freedom_card
  @current_box = other_player.current_box
  self
end

The @ relate to the instance variable of the class Player. you actually do nothing, just setting some variables and return self, which is a class, not an instance

You could do it with

def self.copia(other_player)
  player = new(other_player.name)
  player.from(other_player)
  player
end

def from(other_player)
  @name = other_player.name
  @imprisoned = other_player.imprisoned
  @balance = other_player.balance
  @properties = other_player.properties
  @freedom_card = other_player.freedom_card
  @current_box = other_player.current_box
end

Upvotes: 2

Related Questions