[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Protected methods and class methods

Gioele Barabucci

1/20/2006 7:34:00 PM

Hi,

is there a way to call a protected method of a class from a static method of
the same class? Or to acces an instance variable of a class from a static
method of the same class?

Now I'm facing a problem. I use some static methods as "factory methods", to
create "prefilled" class instances. These methods can't access the protected
methods of the same class. Is this behavior intentional? Is there clean
solution to this problem? If not, how can I work around this problem? This is
a public class, so I don't want to add other params to initialize.

I get this error

irb(main):032:0> Info.fromBytes("\010\008")
NoMethodError: protected method `length=' called for #<Info:0x300c3b70
@length=nil, @typeID=8>
from (irb):23:in `fromBytes'

with this class

class Info
def initialize(typeID)
@typeID = typeID
@length = nil
end

attr_reader :typeID

def length
if @length.nil?
@length = veryLongMathCalcs()
end
return @length
end

def Info.fromBytes(bytes)
typeID = bytes[0, 1].unpack("c")[0]
length = bytes[1, 1].unpack("c")[0]

info = Info.new(typeID)
info.length = length ## <<< this is the error!

return info
end

protected
attr_writer :length

end

--
Gioele <dev@gioelebarabucci.com>



3 Answers

Ross Bamford

1/21/2006 12:46:00 AM

0

On Sat, 2006-01-21 at 04:34 +0900, Gioele Barabucci wrote:

> Now I'm facing a problem. I use some static methods as "factory methods", to
> create "prefilled" class instances. These methods can't access the protected
> methods of the same class. Is this behavior intentional?

I believe so. Because the class Info is itself an instance of Class,
while the instance is an instance of Info, which is entirely unrelated
to Class (apart from the common ancestor, Object). So there's no reason
for protected instance methods on Info to be available to methods on the
class itself.

(I think static methods are usually referred to as class methods in
Ruby. *nothing* is static here).

Access modifiers can be pretty surprising depending where you're coming
from. Check out (if you haven't already):

http://www.whytheluckystiff.net/ruby/pickaxe/html/tut_class...

> Is there clean solution to this problem? If not, how can I work around this
> problem? This is a public class, so I don't want to add other params
> to initialize.

> I get this error
>
> irb(main):032:0> Info.fromBytes("\010\008")
> NoMethodError: protected method `length=' called for #<Info:0x300c3b70
> @length=nil, @typeID=8>
> from (irb):23:in `fromBytes'
>
> with this class
>
> [ ... snipped ...]

Maybe try this workaround. I've also changed a few things to be more
'Rubyish', but you can just ignore that if you like :)

class Info
def initialize(type_id)
@type_id = type_id
@length = nil
end

attr_reader :type_id

def length
@length ||= very_long_math_calcs
end

def Info.from_bytes(bytes)
type_id = bytes[0,1].unpack("c")[0]
len = bytes[1,1].unpack("c")[0]

info = Info.new(type_id)
info.instance_eval { self.length = len } ## <<< changed!

# or (if you don't care about encapsulation here):
# info.instance_eval { @length = len }

info
end

# maybe don't need this now?
protected
attr_writer :length
end

# Noticed a potential error in your input - \008 isn't valid octal :)
p Info.from_bytes("\010\015")
#=> #<Info:0xb7f7b228 @length=13, @type_id=8>

Hope that helps,
Ross

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk



Gioele Barabucci

1/22/2006 5:57:00 PM

0

On Saturday 21 January 2006 01:46, Ross Bamford wrote:
> On Sat, 2006-01-21 at 04:34 +0900, Gioele Barabucci wrote:
> > Now I'm facing a problem. I use some static methods as "factory methods",
> > to create "prefilled" class instances. These methods can't access the
> > protected methods of the same class. Is this behavior intentional?
>
> I believe so. Because the class Info is itself an instance of Class,
> while the instance is an instance of Info, which is entirely unrelated
> to Class (apart from the common ancestor, Object). So there's no reason
> for protected instance methods on Info to be available to methods on the
> class itself.
Instead it makes sense to me to be able to use Info protected methods from
Info class methods. I see no need for 'Class' methods to be able to use
protected members of an arbitrary class, but this is a particular case! Both
methods are strictly related to Info (and its subclasses, but this is just a
detail).

> (I think static methods are usually referred to as class methods in
> Ruby. *nothing* is static here).
Ah, my C++ heritage :)

> Maybe try this workaround.
>
> info = Info.new(type_id)
> info.instance_eval { self.length = len } ## <<< changed!
>
> Hope that helps,
> Ross
Yes, it worked fine. Just I'm not so happy when I have to use *_eval :( I feel
like cheating. Anyway it is better to have such a shortcut than not :)

--
Gioele <dev@gioelebarabucci.com>


Ross Bamford

1/22/2006 7:58:00 PM

0

On Mon, 2006-01-23 at 02:56 +0900, Gioele Barabucci wrote:
> On Saturday 21 January 2006 01:46, Ross Bamford wrote:
> > On Sat, 2006-01-21 at 04:34 +0900, Gioele Barabucci wrote:
> > > Now I'm facing a problem. I use some static methods as "factory methods",
> > > to create "prefilled" class instances. These methods can't access the
> > > protected methods of the same class. Is this behavior intentional?
> >
> > I believe so. Because the class Info is itself an instance of Class,
> > while the instance is an instance of Info, which is entirely unrelated
> > to Class (apart from the common ancestor, Object). So there's no reason
> > for protected instance methods on Info to be available to methods on the
> > class itself.
> Instead it makes sense to me to be able to use Info protected methods from
> Info class methods. I see no need for 'Class' methods to be able to use
> protected members of an arbitrary class, but this is a particular case! Both
> methods are strictly related to Info (and its subclasses, but this is just a
> detail).
>

Yes, I can see the logic in that, and I don't disagree that it'd
probably make sense in some respects, but now I've become more familiar
with Ruby I think I probably _would_ find it surprising if protected
methods worked that way. Things are often more simple (and elegant) than
you'd imagine I suppose...

> > Maybe try this workaround.
> >
> > info = Info.new(type_id)
> > info.instance_eval { self.length = len } ## <<< changed!
> Yes, it worked fine. Just I'm not so happy when I have to use *_eval :( I feel
> like cheating. Anyway it is better to have such a shortcut than not :)

Definitely :)

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk