Self.clone.replace(super)?

Hi. Could anyone help me understand the following? I am reading a
piece of code that someone else wrote.

class RegexAlternation < Array
def sort
self.clone.replace(super)
end

def uniq
  self.clone.replace(super)
end

def map
  self.clone.replace(super {|x| yield(x)})
end

def delete_if
  self.clone.replace(super {|x| yield(x)})
end

def select
  self.clone.replace(super {|x| yield(x)})
end

end

It looks like overriding the existing methods. But the definitions are
very simple, so I am kinda lost here.

I appreciate if you provide some test codes to see what they do.

soichi

On Thu, Jul 5, 2012 at 11:41 AM, Soichi I. [email protected]
wrote:

  self.clone.replace(super)
def select
  self.clone.replace(super {|x| yield(x)})
end

end

It looks like overriding the existing methods. But the definitions are
very simple, so I am kinda lost here.

I appreciate if you provide some test codes to see what they do.

These super class methods will return Array instances but the author
wanted to make sure they return instances of RegexAlternation in class
RegexAlternation.

Few remarks: “self.” is superfluous. “clone” should be replaced by
“dup” because otherwise methods will break on a frozen instance.

Generally it’s a bad idea IMHO to inherit core classes. For example,
someone testing for Array will receive true and might be tempted to do
things with the instance which do not make sense for a
RegexAlternation. It’s better to create a completely unrelated class
which can still implement the same API (or part of it) as the wrapped
class if necessary.

Kind regards

robert

These super class methods will return Array instances but the author
wanted to make sure they return instances of RegexAlternation in class
RegexAlternation.

Few remarks: “self.” is superfluous. “clone” should be replaced by
“dup” because otherwise methods will break on a frozen instance.

Thanks. It makes sense now.

Generally it’s a bad idea IMHO to inherit core classes. For example,
someone testing for Array will receive true and might be tempted to do
things with the instance which do not make sense for a
RegexAlternation. It’s better to create a completely unrelated class
which can still implement the same API (or part of it) as the wrapped
class if necessary.

Huh, thanks for the tip. I will be careful.

soichi

On Thursday, July 5, 2012 5:52:22 AM UTC-4, Robert K. wrote:

end
  self.clone.replace(super {|x| yield(x)})

I appreciate if you provide some test codes to see what they do.
things with the instance which do not make sense for a
RegexAlternation. It’s better to create a completely unrelated class
which can still implement the same API (or part of it) as the wrapped
class if necessary.

I’m actually slightly surprised that it doesn’t return a new instance of
the subclass without such modifications. B/c you are right. Things like
this do severely limit the utility of subclassing.

Seems to me, the OOP ideals of inheritance never really worked out.
Maybe
things are different in Javaland, but you would think, inheritance
really
lived up to it’s purpose, there would be large libraries of reusable
class
systems. Perhaps there are other reasons, but we never see such things.

In Rubyland, it seems the only thing inheritance is good for is the
creation of a base class for adapters, and even that could be managed
via
mixins if necessary.

Sometimes I wonder if we could do just as well toss out inheritance
altogether and simply provide more convenient and efficient support for
delegation.

On Thu, Jul 5, 2012 at 3:27 PM, Intransition [email protected]
wrote:

class RegexAlternation < Array
end
It looks like overriding the existing methods. But the definitions are

Generally it’s a bad idea IMHO to inherit core classes. For example,
someone testing for Array will receive true and might be tempted to do
things with the instance which do not make sense for a
RegexAlternation. It’s better to create a completely unrelated class
which can still implement the same API (or part of it) as the wrapped
class if necessary.

I’m actually slightly surprised that it doesn’t return a new instance of the
subclass without such modifications.

I think one of the reasons is that you do not know how the sub class
construction looks like. The code which works in the super class
might fail in the sub class even if it is unchanged just because the
sub class inherits Singleton or has a different #initialize method.

B/c you are right. Things like this do severely limit the utility of
subclassing.

I generally think that sub classing is overrated. Implementing
interfaces (which is not necessary in Ruby) is much more common. Only
languages like Eiffel which have a much, much larger toolset to
control inheritance use inheritance more often. Only if you can do
inheritance selectively and control the public interface of the sub
class you can use it more widely (e.g. pure implementation
inheritance).

Seems to me, the OOP ideals of inheritance never really worked out. Maybe
things are different in Javaland, but you would think, inheritance really
lived up to it’s purpose, there would be large libraries of reusable class
systems. Perhaps there are other reasons, but we never see such things.

The number of levels where you can reasonably inherit in a library is
probably limited. For example, java.util uses inheritance quite a lot
but even there inheritance chains are not so deep. Example

ArrayList → AbstractList → AbstractCollection

Additionally there are some interfaces implemented across the hierarchy.

In Rubyland, it seems the only thing inheritance is good for is the creation
of a base class for adapters, and even that could be managed via mixins if
necessary.

Sometimes I wonder if we could do just as well toss out inheritance
altogether and simply provide more convenient and efficient support for
delegation.

Well, SimpleDelegator is there and does a pretty good job already.
Maybe it takes only few things more, e.g.

class Module
def delegate(member, *methods)
methods.each do |method|
class_eval %Q{def #{method}(*a,&b) self.#{member}.#{method}(*a,&b)
end}
end
self
end
end

X = Struct.new :foo do
delegate :foo, :length, :encoding
end

x = X.new “abc”
p x.length, x.encoding

Kind regards

robert