Feature #7914
openCase for local class methods
Description
=begin
Here is a use case for local class methods.
Say we wish to give certain classes and all subclasses a special name.
class X
def self.special_name
"special:#{name}"
end
end
class Y < X; end
class Z < Y; end
Z.special_name #=> "special:Z"
But what if Y has a unique special name?
class Y < X
def special_name
'unique:Y'
end
end
Problem that arises:
Z.special_name #=> "unique:Y" # wrong!
Currently, to solve this would require creating an additional method, e.g. unique_name
and redefine special_name
to first look for unique_name then fallback to default special name if non-found. It works, but adds additional complexity to API.
Nicer solution would be local class methods.
class Y < X
def special_name
'unique:Y'
end
local :special_name
end
Y.special_name #=> "unique:Y"
Z.special_name #=> "special:Z"
The idea being that local class methods are skipped in super/lookup chain.
This idea is not without precedence. Module class methods can be thought of as being local. So this idea has other side of the notion, that modules could have class methods that are not skipped over in the super/lookup chain. In that case we would need a term that means opposite of local, so I'll use nonlocal
:
module M
def self.q; "q"; end
nonlocal :q
end
class X
include M
end
X.q #=> "q"
=end
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) over 11 years ago
This doesn't seem to be supported by any OO concept I've heard about and basically breaks the conceptual inheritance model in OO in my opinion. I wouldn't like to have to debug a code that behaved like this. It would make understanding an existent code base much harder in my opinion. Don't you think so?
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) over 11 years ago
What about the code below?
class Y < X
def special_name
self.class.name == 'Y' ? 'unique:Y' : super
end
end
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) over 11 years ago
Maybe you could ask for some special method/keyword to know if the class is the same as the declared one (instead of some inheriting class):
def special_name
local_class? ? 'unique:Y' : super
end
Or instead of "local_class" you could ask if it has been called as a "super" method:
def special_name
called_by_super? ? super : 'unique:Y'
end
Updated by ko1 (Koichi Sasada) over 11 years ago
- Assignee set to matz (Yukihiro Matsumoto)
- Target version changed from 2.1.0 to 2.6
(I don't have any idea about this ticket. but I feel the name `local' recall perl)
Updated by nobu (Nobuyoshi Nakada) over 11 years ago
It seems trivial and usually avoidable.
I guess it could achieve with Module#using.
Updated by trans (Thomas Sawyer) over 11 years ago
@rosenfeld (Rodrigo Rosenfeld Rosas) Maybe I approached this backwards. I just wanted to show one possible use case for supporting local vs. non-local class methods. Your in-method conditional solution works for this specific case, true. But how well does it translate to other cases? For instance, it would not work with anonymous classes. called_by_super is an interesting notion, but after some thought it feels like a make shift approach that only address part of the wider issue. The module non-local side of this is important too. And its use case is much more obvious --everywhere the included/ClassMethods hack is used.
Updated by funny_falcon (Yura Sokolov) over 11 years ago
Thomas Sawyer, you are the language troll, IMHO.
(But, maybe I'm too)
Everyone else, excuse me for not being polite.
23.02.2013 12:17 пользователь "trans (Thomas Sawyer)" transfire@gmail.com
написал:
Issue #7914 has been updated by trans (Thomas Sawyer).
@rosenfeld (Rodrigo Rosenfeld Rosas) Maybe I approached this backwards. I just wanted to show one
possible use case for supporting local vs. non-local class methods. Your
in-method conditional solution works for this specific case, true. But how
well does it translate to other cases? For instance, it would not work with
anonymous classes. called_by_super is an interesting notion, but after some
thought it feels like a make shift approach that only address part of the
wider issue. The module non-local side of this is important too. And its
use case is much more obvious --everywhere the included/ClassMethods hack
is used.
Feature #7914: Case for local class methods
https://bugs.ruby-lang.org/issues/7914#change-36827Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: next minor=begin
Here is a use case for local class methods.Say we wish to give certain classes and all subclasses a special name.
class X
def self.special_name
"special:#{name}"
end
end
class Y < X; end
class Z < Y; endZ.special_name #=> "special:Z"
But what if Y has a unique special name?
class Y < X
def special_name
'unique:Y'
end
endProblem that arises:
Z.special_name #=> "unique:Y" # wrong!
Currently, to solve this would require creating an additional method, e.g.
unique_name
and redefinespecial_name
to first look for unique_name
then fallback to default special name if non-found. It works, but adds
additional complexity to API.Nicer solution would be local class methods.
class Y < X def special_name 'unique:Y' end local :special_name end Y.special_name #=> "unique:Y" Z.special_name #=> "special:Z"
The idea being that local class methods are skipped in super/lookup chain.
This idea is not without precedence. Module class methods can be thought
of as being local. So this idea has other side of the notion, that modules
could have class methods that are not skipped over in the super/lookup
chain. In that case we would need a term that means opposite of local, so
I'll usenonlocal
:module M def self.q; "q"; end nonlocal :q end class X include M end X.q #=> "q"
=end
Updated by hsbt (Hiroshi SHIBATA) 8 months ago
- Status changed from Open to Assigned