Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Set attribute of superclass dinamically

Reply
Thread Tools

Set attribute of superclass dinamically

 
 
Jeroen v.
Guest
Posts: n/a
 
      04-24-2011
I have the following code

class foo
price_per_liter = 1
price
module bar
def set_price val
self.price_per_liter = val
end
end
end

In this way I can succesfully set the price per liter of the class. How
can I make it dunamically, so I can also set the attribute 'price'?

I tried instance_variable_set(@variable, val), but that doesn't work.
Probably because the variables of the class 'foo' and the module 'bar'
lives independent of each other.

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Brian Candler
Guest
Posts: n/a
 
      04-24-2011
Jeroen v. wrote in post #994745:
> I have the following code
>
> class foo


That's wrong - class names must start with a capital letter

> price_per_liter = 1


That sets a local variable. It's only visible between the 'class' and
'end' excluding any nested 'def', 'class' or 'module' (since each of
those start a new scope for local variables). This is unlikely to be
useful.

> price


That will raise an error - it's not a local variable so it must be a
method call, but your class Foo object doesn't have a method 'price'
either (i.e. def self.price ... )

> module bar


Error again: should be 'Bar' not 'bar'. However I'm not sure why you're
making a module Foo::Bar - it's not a class, and it's not a subclass of
Foo.

> def set_price val
> self.price_per_liter = val


That will call method 'price_per_liter=', but you have not defined one.
Error again.

> end
> end
> end
>
> In this way I can succesfully set the price per liter of the class. How
> can I make it dynamically, so I can also set the attribute 'price'?


I'm not sure what it is you're trying to achieve. Here's a guess:

class Foo
def self.price_per_liter=(val)
@price_per_liter = val
end
def self.price_per_liter
@price_per_liter
end
end

class Bar < Foo
end

Foo.price_per_liter = 133.9
Bar.price_per_liter = 144.9

puts Foo.price_per_liter
puts Bar.price_per_liter

> I tried instance_variable_set(@variable, val), but that doesn't work.
> Probably because the variables of the class 'foo' and the module 'bar'
> lives independent of each other.


It's true that the two classes have separate instance variables (since
each class is a separate object, of class Class). But you should be able
to do

Foo.instance_variable_set(:@price_per_liter, 133.9)

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Jeroen v.
Guest
Posts: n/a
 
      04-24-2011
You're right. I wrote the example code too quick.

In the meantime, I also found another solution that is good for me
(however your solution would also worked):

In the module you can do:
self.send("#{method_name}=", value)
This creates a setter on the fly for the superclass

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Josh Cheek
Guest
Posts: n/a
 
      04-24-2011
[Note: parts of this message were removed to make it a legal post.]

On Sun, Apr 24, 2011 at 9:29 AM, Jeroen v. <> wrote:

> I have the following code
>
> class foo
> price_per_liter = 1
> price
> module bar
> def set_price val
> self.price_per_liter = val
> end
> end
> end
>
> In this way I can succesfully set the price per liter of the class. How
> can I make it dunamically, so I can also set the attribute 'price'?
>
> I tried instance_variable_set(@variable, val), but that doesn't work.
> Probably because the variables of the class 'foo' and the module 'bar'
> lives independent of each other.
>
>

What was the error it gave you? From here, I have a hard time believing you
tried setting the ivar, because your code has two syntax errors (classes and
modules must be constants) a name error (price is neither a local variable
nor a method), and you can not set the price per liter of the class as you
say you did, since price_per_liter is a local variable and there is no
price_per_liter= method, anyway.


Anyway, everything in Ruby is an object, including classes. Every object in
Ruby has a singleton class, which is a class just for that one object (they
are created lazily). Why is this relevant? Because methods are defined in
classes, so defining methods on the object's singleton class will define
methods for that one object. This is what class methods are.

So what about modules? When you extend an object (and classes are objects)
with a module, it gets put in the ancestry chain behind the singleton class.
So when you ask the object for its methods, it looks in the singleton class,
and when it doesn't find it, it goes up the chain into the module, where it
discovers the method.

So, we just define the #price= method in the module, then we extend the
class with the module, and now the class has access to that method.

# define the price method on the
# singleton class of Foo
class Foo
def self.price
@price
end
end

# define the price= method as an
# instance method of Bar
module Bar
def price=(new_price)
@price = new_price
end
end

# put Bar as an ancestor of
# Foo's singleton class
Foo.extend Bar

# tada, everything works
Foo.price # => nil
Foo.price = 5
Foo.price # => 5


You also look like you don't understand the difference between local
variables, instance variables, and methods. In Ruby, all instance variables
are private, and they always begin with the @ sigil. So @price is an
instance variable, and price is either a local variable or a method. When
you say `price_per_liter = 1` in your code above, you are setting a local
variable. If you want to invoke a method on self, you need
`self.price_per_liter = 1` to disambiguate. If you want to set the instance
variable, you need `@price_per_liter = 1`

Note that Ruby has syntactic sugar to turn `self.price = 1` into
`self.price=(1)`, that assignment is just a method call.

 
Reply With Quote
 
Brian Candler
Guest
Posts: n/a
 
      04-24-2011
Jeroen v. wrote in post #994769:
> In the module you can do:
> self.send("#{method_name}=", value)
> This creates a setter on the fly for the superclass


That *calls* the setter method, but only if it already exists. If it
doesn't, it will raise an exception.

You need to provide some code to demonstrate what you're saying.

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to check if another object is my superclass from a function in aneven higher superclass? bart van deenen C++ 6 03-03-2009 02:44 PM
calling superclass __init__ when superclass is object Evan Klitzke Python 0 08-02-2007 05:15 AM
Difference Between Calling SuperClass Constructor or Inherited Set Method crouse@physics.wm.edu Java 3 08-18-2006 11:02 AM
recast a superclass attribute VisionSet Java 4 12-19-2003 09:33 PM
Creating JavaScript Dinamically JMMB ASP .Net 1 08-26-2003 04:18 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57