I was discussing with a (Python) friend last night. I told him that one
thing I liked better about Ruby than Python was that you could add
methods to already existing methods. For instance, if I wanted to add a
rot13 method to the String class, all I have to do is this:
class String
def rot13
tr("A-Za-z", "N-ZA-Mn-za-m")
end
end
"foobar".rot13
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
class myStr(str):
def rot13(self):
trans = maketrans(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm")
newstring = translate(word, trans)
return newstring
myStr("foobar").rot13()
or in Ruby
class MyStr < String
def rot13
tr("A-Za-z", "N-ZA-Mn-za-m")
end
end
MyStr.new("foobar").rot13
His main argument was just that, “It’s the Wrong Way ™ to do it”. To
me, it just seems like extra code and added complexity.
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
I’d also like to know if other OO languages (SmallTalk, Eiffel, Sather,
etc.) allow class modifications.
I was discussing with a (Python) friend last night. I told him that one
thing I liked better about Ruby than Python was that you could add
methods to already existing methods. For instance, if I wanted to add a
rot13 method to the String class, all I have to do is this:
class String
> def rot13
> tr("A-Za-z", "N-ZA-Mn-za-m")
> end
> end
>
> "foobar".rot13
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
I tend to go for the adding methods approach, but there’s always the
issue of name conflicts among different libraries…
For what it’s worth, personally I wouldn’t subclass String to get
rot13 functionality, even if I were opposed to create String#rot13.
I’d rather do something like:
class Rot13
def self.
str.tr(“A-Za-z”, “N-ZA-Mn-za-m”)
end
end
I was discussing with a (Python) friend last night. I told him that one
thing I liked better about Ruby than Python was that you could add
methods to already existing methods. For instance, if I wanted to add a
rot13 method to the String class, all I have to do is this:
class String
> def rot13
> tr("A-Za-z", "N-ZA-Mn-za-m")
> end
> end
>
> "foobar".rot13
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
class MyStr < String
> def rot13
> tr("A-Za-z", "N-ZA-Mn-za-m")
> end
> end
>
> MyStr.new("foobar").rot13
His main argument was just that, “It’s the Wrong Way ™ to do it”. To
me, it just seems like extra code and added complexity.
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
I can’t speak of it being a bad idea, but a related feature of Ruby that
may be even more important than extending classes is extending objects.
(I don’t know, can Python even dream of doing this?)
irb(main):001:0> s = “fred”
“fred”
irb(main):002:0> module Fred
irb(main):003:1> def rot13
irb(main):004:2> tr(“A-Za-z”,“N-ZA-Mn-za-m”)
irb(main):005:2> end
irb(main):006:1> end
nil
irb(main):007:0> s.extend Fred
“fred”
irb(main):008:0> s.rot13
“serq”
In this case I don’t pollute the class and I don’t have to
make the expense of subclassing a big class like String.
?? In Ruby, it simply adds a private method to the current object.
So, if Python does the same (allowing you to add methods to instances
of objects at runtime) then why would being able to add methods to a
class of objects at runtime be the wrong thing?
Granted I think in Ruby the inclination to add methods to existing base
classes instead of subclassing them may be more common than it should
be, but the feature is certainly one that makes Ruby very powerful when
done right.
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
–
Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
[python code removed… washing hands…]
His main argument was just that, “It’s the Wrong Way ™ to do it”. To
me, it just seems like extra code and added complexity.
It is the Right Way To Do It if your code passes all its unit and
acceptance tests. It is the Wrong Way To Do It if your code fails to
perform as expected. Beyond that, who cares?
You might perform some trivial benchmark to compare the two on a variety of
base classes and a variety of common “extensions” and reach some overall
efficiency conclusion, though.
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
Nope, can’t say.
Personally if I have a function that takes a string and only a string (like
the example Rot13) then I would extend the String class. Otherwise, while
programming, I have to remember if my strings (lowercase) are Strings or
MyStrings in order to remember which methods they have access to.
But it depends on the application. Maybe in some cases I want two separate
kinds of strings… kind of like how we have lots of separate kinds of
numbers.
-michael
···
On Thursday 19 September 2002 07:20, Vincent Foley wrote:
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
[snippage]
His main argument was just that, “It’s the Wrong Way ™ to do it”. To
me, it just seems like extra code and added complexity.
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
I think it could be considered bad because it can produce
alergic reactions between libraries.
For example:
— LibA
class String
def rot13
tr(A-Za-z,…)
end
end
— LibB
class String
def rot13
puts “rotate 13 degrees”
end
end
···
On Thu, Sep 19, 2002 at 09:20:13PM +0900, Vincent Foley wrote:
require liba
require libb
“fred”.rot13 #=> this will probably not do what you want it to.
Since both libraries have redefined a core class and have added
a method with the same name, there will ultimately be a problem
in the code.
This is why I avoid modifying core libraries and I hope other
library writers do as well.
–
Jim Freeze
Programming Ruby
def initialize; fun; end
A language with class
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class:
He is right that adding methods to an already-defined class is
generally a bad idea. There are some valid reasons to do that, but
99% of the time there is an alternative.
Subclassing is one such alternative. Extending an instance of a
class is another alternative. Creating a new method that takes your
object as an explicit parameter instead of as an implicit parameter
is a third alternative.
Correct me if I’m wrong, but I think python does let you add methods
at run-time:
[pbrannan@zaphod pbrannan]$ python
Python 2.2.1c2 (#1, Apr 8 2002, 18:12:08)
[GCC 3.0.4] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
class Foo:
… def foo(self):
… print “foo!”
…
f = Foo()
f.foo()
foo!
f.bar()
Traceback (most recent call last):
File “”, line 1, in ?
AttributeError: Foo instance has no attribute ‘bar’
def bar(self):
… print “bar!”
…
Foo.dict[‘bar’] = bar
f.foo()
foo!
f.bar()
bar!
Paul
···
On Thu, Sep 19, 2002 at 09:20:13PM +0900, Vincent Foley wrote:
Subclassing is, I think, the thing to do if you need to extend the
behavior of a class. The case where method-adding becomes useful is
when you need to extend Ruby itself, because subclassing doesn’t alter
the anonymous operators or the classes of object returned by Ruby’s
builtin methods.
For example, if you add a specialized sort function to Hash:
class MyHash < Hash
def sortedkeys
keys.sort
end
end
a = { “foo” => “bar” }
‘a’ will still be a Hash, not a MyHash. There’s no way to tell the {}
constructor to return a MyHash.
And builtins will still return builtin classes:
class MyString < String
def rot13
tr(“A-Za-z”, “N-ZA-Mn-za-m”)
end
end
hex = sprintf(“0x%x”, 12345)
‘hex’ will be an ordinary String, not a MyString. If you tried to do
this with subclassing, you’d have to convert everything that came out
of an anonymous constructor or builtin method into the subclassed
object, which would be tedious.
I was discussing with a (Python) friend last night. I told him that one
thing I liked better about Ruby than Python was that you could add
methods to already existing methods.
[snipped example]
But my friend told me that Python didn’t have that because it was not a
good thing and it was not the proper way to do it. He said that the
true way of doing it, is to subclass (since Python 2.2 can now subclass
builtin types) the base class
[snipped another example]
His main argument was just that, “It’s the Wrong Way ™ to do it”. To
me, it just seems like extra code and added complexity.
First, note that the subclassing technique will not work if you do not
create the objects yourself (i.e. they are created by another part of the
system and you cannot control how they are created.) You could use a
“copy constructor” technique in your subclass to get around this, but it’s
often more trouble than it’s worth and also less efficient.
That said, it’s true that most of the time subclassing is a better idea
because adding methods to an existing class can sometimes lead to name
clashes. Even then, though, you might be better off by dynamically adding
a singleton method to an individual object, rather than an entire class:
my_string = get_my_string_from_somewhere()
def my_string.rot13
tr(“A-Za-z”, “N-ZA-Mn-za-m”)
end
This way your string has rot13 capabilities but other strings will not be
affected by this.
I posted some arguments in favor of the Ruby approach to comp.lang.python
a while back. The post can be found at:
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
Currently it is not great idea because name crash in method names.
But if matz introduce selector namespace into Ruby, we can avoid the
problem.
If name crash can be solved (by selector namespace or some prefix),
I think it is good idea. For example, we don’t need Visitor pattern
with such modifiable class.
I’d also like to know if other OO languages (SmallTalk, Eiffel, Sather,
etc.) allow class modifications.
Various (but mainly research) languages have it:
CLOS, AspectJ, MultiJava, Cecil, MixJuice etc.
The author of a paper of MultiJava calls the modifiable class `open
class’.
Can you enligthen me and tell me if it’s really that bad an idea to add
methods to an existing class, or if he’s just being a Python zealot?
I think it could be considered bad because it can produce
alergic reactions between libraries.
Clearly this is a serious problem, though at the same time I think the
power of all this is just too great to go unused.
<signature_tune>
This is where the (stagnated, I’m afraid) Ruby Behaviors package comes
in. I have to regard it as proof-of-concept more than anything
else… but anyway:
class String
def rot13
"first version"
end
end
require 'behaviors-0.0.1/lib/behaviors.rb'
class Behavior
class ROT13 < Definer
def start
rot13 = "def rot13; 'behaviors version'; end"
define(String, "rot13", rot13)
end
end
end
b = Behavior.new(:ROT13)
puts "abc".rot13
b.adopt { puts "abc".rot13 } # block form of adopt
puts "abc".rot13
# =>
# first version
# behaviors version
# first version
</signature_tune>
David
···
On Thu, 19 Sep 2002, Jim Freeze wrote:
On Thu, Sep 19, 2002 at 09:20:13PM +0900, Vincent Foley wrote:
Actually, because in Ruby a class definition is never closed, don’t we
fundamentally have a similar problem (although possibly with much less
probability, especially when module is used) by subclassing as adding a
method? In other words, the name of subclass that we create may already
be used as a name of some other class.
Regards,
Bill
···
============================================================================
Jim Freeze jim@freeze.org wrote:
I think it could be considered bad because it can produce
alergic reactions between libraries.
He is right that adding methods to an already-defined class is
generally a bad idea. There are some valid reasons to do that, but
99% of the time there is an alternative.
Well I generally try to avoid this too - but I don’t believe that there
is a very strong case against this (well as long as your code isn’t
intended as an extension for general consumption).
I’d also like to know if other OO languages (SmallTalk, Eiffel, Sather,
etc.) allow class modifications.
Various (but mainly research) languages have it:
CLOS, AspectJ, MultiJava, Cecil, MixJuice etc.
The author of a paper of MultiJava calls the modifiable class `open
class’.
This is a rather interesting collection of languages
3 out 5 have multi-method support of some kind (I never
heard of MixJuice so maybe it is really 4 out 5).
This runs squarely against a prominent argument of the anti multi-method camp'' that Ruby's open classes’’
(a very descriptive term btw.) somehow reduce the need
of method overloading.
Apparently the exact opposite seems to be true:
Method overloading (preferable in the incarnation of
full blown multi-methods) and '‘class openness’ seem
to form a very strong synergy …
Fri, 20 Sep 2002 14:40:35 +0900, Christoph chr_news@gmx.net pisze:
This runs squarely against a prominent argument of the anti multi-method camp'' that Ruby's open classes’’ (a very descriptive
term btw.) somehow reduce the need of method overloading.
Apparently the exact opposite seems to be true: Method overloading
(preferable in the incarnation of full blown multi-methods) and
'‘class openness’ seem to form a very strong synergy …
It seems logical to me. If methods are standalone objects, it’s
easy to do both multidispatch (looking up classes inside a method,
not methods inside a class - lookup is more complicated but there is
no problem where to look up) and creating methods anytime (classes
aren’t modified so it makes no sense to freeze them; they are methods
which are modified).
You can create the subclass inside a “namespace”, e.g.:
module MyProject
class String < ::String
…
end
end
You can also create an anonymous subclass:
class Foo
@@my_string = Class.new(String)
end
Paul
···
On Fri, Sep 20, 2002 at 01:20:37AM +0900, William Djaja Tjokroaminata wrote:
Actually, because in Ruby a class definition is never closed, don’t we
fundamentally have a similar problem (although possibly with much less
probability, especially when module is used) by subclassing as adding a
method? In other words, the name of subclass that we create may already
be used as a name of some other class.
This runs squarely against a prominent argument of the
``anti multi-method camp'' that Ruby's ``open classes''
(a very descriptive term btw.) somehow reduce the need
of method overloading.