I'm writing a class to encapsulate a 'job'. The job will have variables
such as name, id, resources, dependencies etc and some of these will be
common across all instances. I'd like to be able to set these common
variables once and not have to repeat it for every instance. What's the
best way of accomplishing this?
So far I've seen a lot of articles that steer you towards using class
instance variables instead of class variables but I can't find examples
of how to use these from within an instance. Is that possible?
An instance variable is prefaced by @, where a class variable is
prefaced by @@. Here's a small example:
class Thingy
@@thingies = 0
def initialize(name) @my_name = name
@@thingies += 1
puts "A new thingy is here!"
end
def whatsMyName
puts "This thingy is named '#{@my_name}'."
end
def howMany?
puts "So far you have created #{@@thingies} thingies."
end
end
The @@thingies class variable is shared by all instances of the class.
Changing that variable in any one of the classes will change it for all
of them.
That's interesting. I never considered how they'd behave under
inheritance. Has there been a discussion about changing the behavior so
that the subclasses don't alter the superclass variable? (Like the
subclass would copy in the superclass var at definition but it would be
a separate instance from the superclass object.)
Actually, now that I'm thinking about it the existing behavior sort of
what makes more sense. I'd think that subclasses would be better
instantiating their own class vars rather than expecting a unique copy
of the superclass var. I can see why you'd want the class instance vars
rather than modifying the existing mechanic. On the other hand, maybe a
new variable type to encapsulate the behavior of a class instance var in
the way that it's being used here would be something worth discussing?
Probably a better way than adding a new var type but it could be more
versatile than just for use with civ for subclasses. Maybe something
like 'self_attr_accessor' or 'class_attr_accessor'?
Concerning an attr for civ's, would it really be detrimental, though?
True it's something that would very rarely be used, but it almost feels
like it's something that belongs there. I guess what I mean is, if
attr_accessor exists it feels to me like there should be a sort of
class-level equivalent. Maybe that's just me, though. This has
somewhat moved beyond my depth.
I then also understood that there was no need for me to use them.
Since I wasted time, and also had a bug, I decided that day to no longer
use class variables at all.
There are a very few use cases where they may seem not totally useless,
but so far I myself did not need them at all. And I follow a philosophy
that less (code) is more.
I think he is looking for class instance variables.
class Foo @class_ivar = 3
def self.class_ivar() @class_ivar; end
def bar(a)
puts "#{a} + #{self.class.class_ivar} = #{a + self.class.class_ivar}"
end
end
foo = Foo.new
foo.bar(6) # 6 + 3 = 9
cr
···
On Dec 20, 2011, at 12:26 PM, Khat Harr wrote:
An instance variable is prefaced by @, where a class variable is
prefaced by @@. Here's a small example:
class Thingy
@@thingies = 0
def initialize(name) @my_name = name
@@thingies += 1
puts "A new thingy is here!"
end
def whatsMyName
puts "This thingy is named '#{@my_name}'."
end
def howMany?
puts "So far you have created #{@@thingies} thingies."
end
end
The @@thingies class variable is shared by all instances of the class.
Changing that variable in any one of the classes will change it for all
of them.
I don't see any point in that, class ivars seem sufficient to me. What
would be nice, though, is an attr_accessor equivalent that defines methods
for both the class and instance.
(overly simple example)
class Class
def whatever_accessor(meth_name)
delegate_to_class meth_name
singleton_class.instance_eval do
attr_accessor meth_name
end
end
def delegate_to_class(meth_name)
define_method meth_name do |*args, &block|
self.class.send meth_name, *args, &block
end
end
end
class Foo
whatever_accessor :bar
self.bar = :baz
end
Foo.new.bar # => :baz
···
On Tue, Dec 20, 2011 at 9:42 PM, Khat Harr <myphatproxy@hotmail.com> wrote:
Actually, now that I'm thinking about it the existing behavior sort of
what makes more sense. I'd think that subclasses would be better
instantiating their own class vars rather than expecting a unique copy
of the superclass var. I can see why you'd want the class instance vars
rather than modifying the existing mechanic. On the other hand, maybe a
new variable type to encapsulate the behavior of a class instance var in
the way that it's being used here would be something worth discussing?
Concerning an attr for civ's, would it really be detrimental, though?
Do you mean an attr_accessor like method for a class instance itself?
True it's something that would very rarely be used, but it almost feels
like it's something that belongs there. I guess what I mean is, if
attr_accessor exists it feels to me like there should be a sort of
class-level equivalent. Maybe that's just me, though. This has
somewhat moved beyond my depth.
If you mean such a method then yes, that might be a reasonable thing to have.
Kind regards
robert
···
On Wed, Dec 21, 2011 at 6:48 PM, Khat Harr <myphatproxy@hotmail.com> wrote:
Actually, now that I'm thinking about it the existing behavior sort of
what makes more sense. I'd think that subclasses would be better
instantiating their own class vars rather than expecting a unique copy
of the superclass var. I can see why you'd want the class instance vars
rather than modifying the existing mechanic. On the other hand, maybe a
new variable type to encapsulate the behavior of a class instance var in
the way that it's being used here would be something worth discussing?
I opt for completely removing class variables because they lead to
confusion without end. I don't see the need for a new type of
variable either. For one, it is an open question if state really
should be managed on the class level. It may be much more appropriate
for Shareed to have a container object which holds a number of
instances and manages common state. If you need that state in
instances you can always have a backward reference to the container.
(You need that anyway if you want to avoid joining multiple containers
for a 1:n relationship.) If state is managed by the class then you
cannot partition the set of instances. And in case of this thread it
seems state is better not held in the class instance, because that
should manage class state while here we are talking about state which
is common to all instances. Just because it's easy to do or
convenient does not mean that storing this in the class is necessary a
good idea.
I don't see any point in that, class ivars seem sufficient to me. What
would be nice, though, is an attr_accessor equivalent that defines methods
for both the class and instance.
I find that a bad idea: this easily leads to confusion and if you want
the same attribute in the class and all instances then you better make
that explicit. This should be a very rare case anyway. The only
thing which comes to mind where this seems remotely useful would be
default values for fields. But in this case I'd rather name fields
differently because they mean something different:
class Foo
class <<self
attr_accessor :name_default
end
attr_writer :name
def name @name || self.class.name_default
end
end
irb(main):025:0> Foo.name_default = "X"
=> "X"
irb(main):026:0> f = Foo.new
=> #<Foo:0x1018c06c>
irb(main):027:0> f.name
=> "X"
irb(main):028:0> f.name = "bar"
=> "bar"
irb(main):029:0> f.name
=> "bar"
irb(main):030:0> Foo.name_default
=> "X"
Kind regards
robert
···
On Wed, Dec 21, 2011 at 5:34 AM, Josh Cheek <josh.cheek@gmail.com> wrote:
On Tue, Dec 20, 2011 at 9:42 PM, Khat Harr <myphatproxy@hotmail.com> wrote:
Yeah, sorry, it was late. The need I actually come across isn't state
based, but functionality based. For example, HTTParty's get method. From
outside it's nice to be able to say `HTTParty.get(...)` but from inside
they don't want to have to say `self.class.get(...)` so that is an example
of a class level method that should be available to instances without
having to go find the class. I find that need occasionally. Or sometimes
I'm looking at some method and realizing it really could be a class method,
and that no one can use it without instantiating, but it's pretty obnoxious
to have to instantiate a class just to call some method that doesn't depend
on instances.
···
On Wed, Dec 21, 2011 at 2:50 AM, Robert Klemme <shortcutter@googlemail.com>wrote:
On Wed, Dec 21, 2011 at 5:34 AM, Josh Cheek <josh.cheek@gmail.com> wrote:
> On Tue, Dec 20, 2011 at 9:42 PM, Khat Harr <myphatproxy@hotmail.com> > wrote:
>
>> Actually, now that I'm thinking about it the existing behavior sort of
>> what makes more sense. I'd think that subclasses would be better
>> instantiating their own class vars rather than expecting a unique copy
>> of the superclass var. I can see why you'd want the class instance vars
>> rather than modifying the existing mechanic. On the other hand, maybe a
>> new variable type to encapsulate the behavior of a class instance var in
>> the way that it's being used here would be something worth discussing?
I opt for completely removing class variables because they lead to
confusion without end. I don't see the need for a new type of
variable either. For one, it is an open question if state really
should be managed on the class level. It may be much more appropriate
for Shareed to have a container object which holds a number of
instances and manages common state. If you need that state in
instances you can always have a backward reference to the container.
(You need that anyway if you want to avoid joining multiple containers
for a 1:n relationship.) If state is managed by the class then you
cannot partition the set of instances. And in case of this thread it
seems state is better not held in the class instance, because that
should manage class state while here we are talking about state which
is common to all instances. Just because it's easy to do or
convenient does not mean that storing this in the class is necessary a
good idea.
> I don't see any point in that, class ivars seem sufficient to me. What
> would be nice, though, is an attr_accessor equivalent that defines
methods
> for both the class and instance.
I find that a bad idea: this easily leads to confusion and if you want
the same attribute in the class and all instances then you better make
that explicit. This should be a very rare case anyway. The only
thing which comes to mind where this seems remotely useful would be
default values for fields. But in this case I'd rather name fields
differently because they mean something different:
class Foo
class <<self
attr_accessor :name_default
end
attr_writer :name
def name @name || self.class.name_default
end
end
irb(main):025:0> Foo.name_default = "X"
=> "X"
irb(main):026:0> f = Foo.new
=> #<Foo:0x1018c06c>
irb(main):027:0> f.name
=> "X"
irb(main):028:0> f.name = "bar"
=> "bar"
irb(main):029:0> f.name
=> "bar"
irb(main):030:0> Foo.name_default
=> "X"
Da: Khat Harr [mailto:myphatproxy@hotmail.com]
Inviato: martedì 27 dicembre 2011 01:43
A: ruby-talk ML
Oggetto: Re: Accessing class instance variables from an instance?
Robert Klemme wrote in post #1037737:
On Wed, Dec 21, 2011 at 6:48 PM, Khat Harr <myphatproxy@hotmail.com> > wrote:
Concerning an attr for civ's, would it really be detrimental, though?
Do you mean an attr_accessor like method for a class instance itself?
Yeah, sorry, it was late. The need I actually come across isn't state
based, but functionality based. For example, HTTParty's get method. From
outside it's nice to be able to say `HTTParty.get(...)` but from inside
they don't want to have to say `self.class.get(...)` so that is an example
You can also say HTTParty.get(...) inside instance methods.
of a class level method that should be available to instances without
having to go find the class. I find that need occasionally. Or sometimes
I'm looking at some method and realizing it really could be a class method,
and that no one can use it without instantiating, but it's pretty obnoxious
to have to instantiate a class just to call some method that doesn't depend
on instances.
Well, then make it a class method. That has the added advantage that
you make the call explicit in instance methods which use it and it is
immediately clear that this method does not manipulate instance state.
I think this make-a-class-method-be-callable-as-instance-method looks
convenient on first sight but on second sight it may just be
obfuscation.
Kind regards
robert
···
On Wed, Dec 21, 2011 at 3:08 PM, Josh Cheek <josh.cheek@gmail.com> wrote: