Home > Net >  why won't this pass the new color into the hash (still learning about def methods and the assig
why won't this pass the new color into the hash (still learning about def methods and the assig

Time:09-22

boat_1 = { "name" => "S. S. Minnow", "color" => "white", "price" => 20000 }
boat_2 = { "name" => "Titanic", "color" => "black", "price" => 700000000 }

class Boat

    def initialize(name, color, price)
        @name = name
        @color = color
        @price = price
    end

    def name
        @name
    end

    def color
        @color
    end

    def boat_2(text)
        @color = text 
    end

end

boat_1 = Boat.new("S. S. Minnow", "white", 20000 )
boat_2 = Boat.new("Titanic", "black", 700000000)

p boat_1
p boat_2

p boat_1.name
boat_2.color = "red"
p boat_2.color

I'm not sure if I am just not wording the method correctly

here is the actual question from my bootcamp if that helps

Rewrite the two hashes to use a class instead. Also write the methods to retrieve the name and the color, and another method to redefine the color.:

I honestly thought it was going to be as simple as just passing a new value into the hash but nothing I have tried so far has worked.

CodePudding user response:

First of all for writing trivial readers and writers on attributes I think that you shuld use attr_reader, attr_writer or for both attr_accesors

After saying that I thin that your code is correct but you writer method on color must be def attriute_name=() blah blah end, please note the = sign in name. so your class will be something like this:

class Boat
  
  def initialize(color, name, price)
    @color = color
    @name = name
    @price = price
  end

  def name
    @name
  end
  
  def color
    @color
  end

  def color=(color)
    @color = color
  end
end

zand using it:

[2] pry(main)> 
[8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* [8] pry(main)* => :color=
[9] pry(main)> b = Boat.new "red", "Pete", 56
=> #<Boat:0x00007f9d7534c230 @color="red", @name="Pete", @price=56>
[26] pry(main)> b.color= "blue"
=> "blue"
[35] pry(main)> pp b
#<Boat:0x00007f9d7534c230 @color="blue", @name="Pete", @price=56>
=> #<Boat:0x00007f9d7534c230 @color="blue", @name="Pete", @price=56>

CodePudding user response:

I am not certain I understand the question, but this is an answer for what I believe it to be.

We are given two hashes:

boat_1 = { "name"=>"S. S. Minnow", "color"=>"white", "price"=>20000 }
boat_2 = { "name"=>"Titanic", "color"=>"black", "price"=>700000000 }

If we wish to obtain, for example, the value of the key "color" for boat_1, we would write

boat_1["name"]
  #=> "S. S. Minnow"

where #=> designates the return value of the the instance method Hash#[] for a given key, the key being the argument of the method.

Similarly, if we wish to change the value of "color" to, say, "red", we might use the method Hash#[]=:

boat_1["color"] = "red"

I'm guessing that the question wants you to create a class, say, "Boat" (but of course the name is unimportant) and create two instances of that class named, perhaps, boat1 and boat2, and show how you would perform operations on those instances comparable to the two shown above for hashes.

You might write that class as follows:

class Boat
  attr_accessor :color 
  attr_reader :name, :price
  def initialize(name, color, price)
    @name = name
    @color = color
    @price = price
  end
end

The class method Module#attr_reader is invoked on self (which equals Boat) when the class definition is parsed. That method merely creates two instance methods:

def name
  @name
end
def price
  @price
end

These methods are called getters.

Similarly, the class method Module::attr_accessor is also invoked on self when the class definition is parsed. It creates both a getter:

def color
  @color
end

and a setter (instance method):

def color=(new_color)
  @color = new_color
end

I would like to emphasize that attr_accessor, attr_reader (and Module::attr_writer) are provided merely for the coder's convenience; if they were not provided in the Ruby core the coder would simply write any needed getters and setters.

We would then create the instances as shown in the question.

boat_1 = Boat.new("S. S. Minnow", "white", 20000)
  #=> #<Boat:0x00007ff90c1d2358 @name="S. S. Minnow", @color="white",
  #     @price=20000>
boat_2 = Boat.new("Titanic", "black", 700000000)
  #=> #<Boat:0x00007ff90c1c03d8 @name="Titanic", @color="black",
  #     @price=700000000>

To obtain the value of boat1's key "name" we would write:

boat_1.name
  #=> "S. S. Minnow"

To change the value of boat_1's key "color" to "red" we would write:

boat_1.color = "red"
  #=> "red"
boat_1
  #=> #<Boat:0x00007ff90c1d2358 @name="S. S. Minnow", @color="red",
  #     @price=20000>

Does this mean that hashes and classes are in any sense interchangeable? The answer is "no".

Suppose we wished to add a key-value pair to an existing hash. We might use the method Hash#[] mentioned earlier:

boat-1["length"] = 6.2

To do something similar with a class we would need to rewrite the class definition (which would be impractable if done dynamically).

If we wished remove a key-value pair in a hash we could use the method Hash#delete:

boat_1.delete("price")

Again, to do that with a class we would have to rewrite the class definition.

Suppose we wished to change the value of the key "name". With the hash we would write:

boat_1[:name] = "Pinta"

If we attempted to do that with the class instance we would obtain the following:

boat_1.name = "Pinta"   
  #=> NoMethodError: undefined method 'name=' for #<Boat:0x00007ff90c1d2358>

This could be a reason for using a class rather than a hash if the coder did not want this value to be changed.

Obviously, there are many things we can do with hashes that do not lend themselves to class instances (such as merging two hashes) and vice-versa.

  • Related