Protected methods and class methods

G

Gioele Barabucci

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
 
R

Ross Bamford

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_classes.html#S4
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
 
G

Gioele Barabucci

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 :)
 
R

Ross Bamford

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...
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 :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top