Below is a sample code that uses the Array instance method for the instance of the class that inherited the Array.
class MyArray<Array
end
m=MyArray.new
n = MyArray.new
added=m+n
putsm.class#MyArray
putsn.class#MyArray
puts added.class#Array
We use +
here.
As mentioned above, added
is an instance of the Array class.
I would like to get a subclass instance at this time.Is there any way?
Additional information
Thank you all for your kind reply.I learned a lot.
The implementation overrides the existing method, and if the return value is superclass, it generates an instance of subclass and uses it as a return value.
I need to use send, and although it looks ugly, I tried using gem.
https://github.com/mmmmmavo/subper_class/blob/master/spec/subper_class_spec.rb
ruby
Array#+
returns Array
, so if you call the parent class +
, it will remain Array
.The only way to change this is to overwrite (override) the +
method (the term "overload operator" is incorrect because the operator is also just a method in Ruby).However, the problem is not only +
but also -
and &
.Based on that, I thought of a way to overwrite it.
class MyArray<Array
def+(_)
MyArray.new(super)
end
def -(_)
MyArray.new(super)
end
def&(_)
MyArray.new(super)
end
def|(_)
MyArray.new(super)
end
end
If you only write super
, call the parent method exactly with the same argument.The return value is Array
, so simply MyArray.new()
it becomes an instance of MyArray
.
Now, four of the same codes came out.For those of you who love DRY, this code doesn't suit you, so let's summarize it.
class MyArray<Array
def self.new_creation_method(*methods)
methods.each do | method |
define_method(method) do | * args, & block |
MyArray.new(super(*args, & block))
end
end
end
new_creation_method:+, :-, :&, :|, :uniq, :sort
end
define_method
is the Module
method for creating instance methods.Ruby can dynamically create instance methods in this way.For more information, see Module#define_method.This super
cannot omit arguments.
As in the code above, a method that returns a new Array
such as uniq
as well as +
and -
can be defined in the same way, as well as passing blocks such as sort
.However, depending on the type and result of the argument, methods that return anything other than Array
cannot be supported, so they need to be handled separately.
As @metropolis said, I think we need to override the Array#+
method.
The original Array#+
method does the following:
If this is done for MyArray:
The code is as follows.(Using the initialization array, we are doing 1,2 at the same time)
class MyArray<Array
def+(x)
MyArray.new(self).concat(x)
end
end
© 2024 OneMinuteCode. All rights reserved.