Let `super` call the parent class over an included module
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have class Boy
that inherits class Person
, and includes module Bipedal
. Both Person
and Bipedal
have versions of #two_legs
.
module Bipedal
def two_legs(name)
puts "#{name} has exactly two limbs used for walking."
end
end
class Person
def two_legs(name)
puts "#{name} has two human legs."
end
end
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
super(@name)
end
end
Since the Bipedal
module is included in Boy
, Bipedal#two_legs
takes precedence over the Person#two_legs
. When I call super
on a Boy
instance, the module Bipedal
takes precedence over the parent class Person
.
johnny = Boy.new('Johnny')
johnny.two_legs
# >> "Johnny has exactly two limbs used for walking."
I want to use one version in one place and the other in another. Bipedal
has other stuff, so I can't comment out include Bipedal
. Is there some standard way to let Boy#two_legs
or super
to use the parent class version instead of the module version as follows?
johnny.two_legs
# >> "Johnny has two human legs."
I came up with this:
Boy.superclass.instance_method(:two_legs).bind(self).call(@name)
which works in place of super(@name)
, but is more complicated than I was expecting.
Again, the question is, is there a standard way to force the parent class to take precedence over the module when calling super
?
ruby inheritance superclass
add a comment |
I have class Boy
that inherits class Person
, and includes module Bipedal
. Both Person
and Bipedal
have versions of #two_legs
.
module Bipedal
def two_legs(name)
puts "#{name} has exactly two limbs used for walking."
end
end
class Person
def two_legs(name)
puts "#{name} has two human legs."
end
end
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
super(@name)
end
end
Since the Bipedal
module is included in Boy
, Bipedal#two_legs
takes precedence over the Person#two_legs
. When I call super
on a Boy
instance, the module Bipedal
takes precedence over the parent class Person
.
johnny = Boy.new('Johnny')
johnny.two_legs
# >> "Johnny has exactly two limbs used for walking."
I want to use one version in one place and the other in another. Bipedal
has other stuff, so I can't comment out include Bipedal
. Is there some standard way to let Boy#two_legs
or super
to use the parent class version instead of the module version as follows?
johnny.two_legs
# >> "Johnny has two human legs."
I came up with this:
Boy.superclass.instance_method(:two_legs).bind(self).call(@name)
which works in place of super(@name)
, but is more complicated than I was expecting.
Again, the question is, is there a standard way to force the parent class to take precedence over the module when calling super
?
ruby inheritance superclass
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59
add a comment |
I have class Boy
that inherits class Person
, and includes module Bipedal
. Both Person
and Bipedal
have versions of #two_legs
.
module Bipedal
def two_legs(name)
puts "#{name} has exactly two limbs used for walking."
end
end
class Person
def two_legs(name)
puts "#{name} has two human legs."
end
end
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
super(@name)
end
end
Since the Bipedal
module is included in Boy
, Bipedal#two_legs
takes precedence over the Person#two_legs
. When I call super
on a Boy
instance, the module Bipedal
takes precedence over the parent class Person
.
johnny = Boy.new('Johnny')
johnny.two_legs
# >> "Johnny has exactly two limbs used for walking."
I want to use one version in one place and the other in another. Bipedal
has other stuff, so I can't comment out include Bipedal
. Is there some standard way to let Boy#two_legs
or super
to use the parent class version instead of the module version as follows?
johnny.two_legs
# >> "Johnny has two human legs."
I came up with this:
Boy.superclass.instance_method(:two_legs).bind(self).call(@name)
which works in place of super(@name)
, but is more complicated than I was expecting.
Again, the question is, is there a standard way to force the parent class to take precedence over the module when calling super
?
ruby inheritance superclass
I have class Boy
that inherits class Person
, and includes module Bipedal
. Both Person
and Bipedal
have versions of #two_legs
.
module Bipedal
def two_legs(name)
puts "#{name} has exactly two limbs used for walking."
end
end
class Person
def two_legs(name)
puts "#{name} has two human legs."
end
end
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
super(@name)
end
end
Since the Bipedal
module is included in Boy
, Bipedal#two_legs
takes precedence over the Person#two_legs
. When I call super
on a Boy
instance, the module Bipedal
takes precedence over the parent class Person
.
johnny = Boy.new('Johnny')
johnny.two_legs
# >> "Johnny has exactly two limbs used for walking."
I want to use one version in one place and the other in another. Bipedal
has other stuff, so I can't comment out include Bipedal
. Is there some standard way to let Boy#two_legs
or super
to use the parent class version instead of the module version as follows?
johnny.two_legs
# >> "Johnny has two human legs."
I came up with this:
Boy.superclass.instance_method(:two_legs).bind(self).call(@name)
which works in place of super(@name)
, but is more complicated than I was expecting.
Again, the question is, is there a standard way to force the parent class to take precedence over the module when calling super
?
ruby inheritance superclass
ruby inheritance superclass
edited Nov 30 '18 at 0:25
anothermh
3,37931733
3,37931733
asked Nov 27 '18 at 0:56
globewalldeskglobewalldesk
329112
329112
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59
add a comment |
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59
add a comment |
3 Answers
3
active
oldest
votes
One could use the method Method#super_method twice. That being a garden-variety Ruby method, I believe it would qualify as a "standard way" to let Boy#two_legs
invoke Person#two_legs
rather than Bipedal#two_legs
.
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
method(:two_legs).super_method.super_method.call(@name)
end
end
willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Note the following.
willie.method(:two_legs).super_method.owner
#=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
#=> Person
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
add a comment |
No, there is no standard way to force a call to super
to walk the ancestors in a specific order. They are walked in a pre-defined order. Take a look at the documentation on calling methods:
When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.
Here is the order of method lookup for the receiver's class or module
R
:
- The prepended modules of
R
in reverse order
- For a matching method in
R
- The included modules of
R
in reverse order
If
R
is a class with a superclass, this is repeated withR
's superclass until a method is found.
Once a match is found method lookup stops.
Since your class Boy
includes the module Bipedal
directly, and since included modules are searched before the superclass, and since searching stops once a match is found, the superclass Person
is never checked.
The same is true when using refinements because the lookup always hits included modules before it checks the superclass.
If you move include Bipedal
into the Person
class then it will work the way you expect because Boy
does not include a module directly, so it will eventually search the superclass where it will find the defined method.
There may be other creative ways you can accomplish this goal, like the Boy.superclass...
example you gave, but you asked if it's possible to change the lookup behavior when calling super
and the answer is no per the documentation.
Shame (or not depending how much sanity you like) that you can't editSomeModule.ancestors
.
– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class methodself.ancestors
in the child class with the desired order does not work.super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec forsuper
.
– anothermh
Nov 27 '18 at 19:34
add a comment |
I don't think you can change how super
works and you can't "super super
" to skip an ancestor but you can use a different ancestor. If you're just including Bipedal
for some of its methods and want to skip a few of them then you could do something like this:
SemiBipedal = Bipedal.dup
SemiBipedal.remove_method(:two_legs)
class Boy < Person
include SemiBipedal
#...
end
Of course johnny.is_a? Bipedal
won't be true anymore and Boy.ancestors
will have SemiBipedal
instead of Bipedal
at index 1 but that might not matter.
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?remove_method
doesn't appear to be private in 2.5.3. You can alwaysSemiBipedal.send(:remove_method, :two_legs)
ormodule SemiBipedal; remove_method :two_legs; end
to kludge around that.
– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and addBipedal.send(:remove_method, :two_legs)
directly toBoy
, assumingBoy
doesn't need theBipedal
version...
– globewalldesk
Nov 28 '18 at 0:21
2
ButBipedal.send(:remove_method, :two_legs)
modifiesBipedal
so everything that uses the module will be affected, hence the copy ofBipedal
(not alias) and removingtwo_legs
from the copy.
– mu is too short
Nov 28 '18 at 0:36
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53491282%2flet-super-call-the-parent-class-over-an-included-module%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
One could use the method Method#super_method twice. That being a garden-variety Ruby method, I believe it would qualify as a "standard way" to let Boy#two_legs
invoke Person#two_legs
rather than Bipedal#two_legs
.
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
method(:two_legs).super_method.super_method.call(@name)
end
end
willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Note the following.
willie.method(:two_legs).super_method.owner
#=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
#=> Person
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
add a comment |
One could use the method Method#super_method twice. That being a garden-variety Ruby method, I believe it would qualify as a "standard way" to let Boy#two_legs
invoke Person#two_legs
rather than Bipedal#two_legs
.
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
method(:two_legs).super_method.super_method.call(@name)
end
end
willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Note the following.
willie.method(:two_legs).super_method.owner
#=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
#=> Person
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
add a comment |
One could use the method Method#super_method twice. That being a garden-variety Ruby method, I believe it would qualify as a "standard way" to let Boy#two_legs
invoke Person#two_legs
rather than Bipedal#two_legs
.
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
method(:two_legs).super_method.super_method.call(@name)
end
end
willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Note the following.
willie.method(:two_legs).super_method.owner
#=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
#=> Person
One could use the method Method#super_method twice. That being a garden-variety Ruby method, I believe it would qualify as a "standard way" to let Boy#two_legs
invoke Person#two_legs
rather than Bipedal#two_legs
.
class Boy < Person
include Bipedal
attr_accessor :name
def initialize(name)
@name = name
end
def two_legs
method(:two_legs).super_method.super_method.call(@name)
end
end
willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Note the following.
willie.method(:two_legs).super_method.owner
#=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
#=> Person
edited Nov 29 '18 at 5:19
answered Nov 28 '18 at 22:04
Cary SwovelandCary Swoveland
71.3k54167
71.3k54167
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
add a comment |
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
This one just works!
– globewalldesk
Nov 29 '18 at 14:27
add a comment |
No, there is no standard way to force a call to super
to walk the ancestors in a specific order. They are walked in a pre-defined order. Take a look at the documentation on calling methods:
When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.
Here is the order of method lookup for the receiver's class or module
R
:
- The prepended modules of
R
in reverse order
- For a matching method in
R
- The included modules of
R
in reverse order
If
R
is a class with a superclass, this is repeated withR
's superclass until a method is found.
Once a match is found method lookup stops.
Since your class Boy
includes the module Bipedal
directly, and since included modules are searched before the superclass, and since searching stops once a match is found, the superclass Person
is never checked.
The same is true when using refinements because the lookup always hits included modules before it checks the superclass.
If you move include Bipedal
into the Person
class then it will work the way you expect because Boy
does not include a module directly, so it will eventually search the superclass where it will find the defined method.
There may be other creative ways you can accomplish this goal, like the Boy.superclass...
example you gave, but you asked if it's possible to change the lookup behavior when calling super
and the answer is no per the documentation.
Shame (or not depending how much sanity you like) that you can't editSomeModule.ancestors
.
– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class methodself.ancestors
in the child class with the desired order does not work.super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec forsuper
.
– anothermh
Nov 27 '18 at 19:34
add a comment |
No, there is no standard way to force a call to super
to walk the ancestors in a specific order. They are walked in a pre-defined order. Take a look at the documentation on calling methods:
When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.
Here is the order of method lookup for the receiver's class or module
R
:
- The prepended modules of
R
in reverse order
- For a matching method in
R
- The included modules of
R
in reverse order
If
R
is a class with a superclass, this is repeated withR
's superclass until a method is found.
Once a match is found method lookup stops.
Since your class Boy
includes the module Bipedal
directly, and since included modules are searched before the superclass, and since searching stops once a match is found, the superclass Person
is never checked.
The same is true when using refinements because the lookup always hits included modules before it checks the superclass.
If you move include Bipedal
into the Person
class then it will work the way you expect because Boy
does not include a module directly, so it will eventually search the superclass where it will find the defined method.
There may be other creative ways you can accomplish this goal, like the Boy.superclass...
example you gave, but you asked if it's possible to change the lookup behavior when calling super
and the answer is no per the documentation.
Shame (or not depending how much sanity you like) that you can't editSomeModule.ancestors
.
– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class methodself.ancestors
in the child class with the desired order does not work.super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec forsuper
.
– anothermh
Nov 27 '18 at 19:34
add a comment |
No, there is no standard way to force a call to super
to walk the ancestors in a specific order. They are walked in a pre-defined order. Take a look at the documentation on calling methods:
When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.
Here is the order of method lookup for the receiver's class or module
R
:
- The prepended modules of
R
in reverse order
- For a matching method in
R
- The included modules of
R
in reverse order
If
R
is a class with a superclass, this is repeated withR
's superclass until a method is found.
Once a match is found method lookup stops.
Since your class Boy
includes the module Bipedal
directly, and since included modules are searched before the superclass, and since searching stops once a match is found, the superclass Person
is never checked.
The same is true when using refinements because the lookup always hits included modules before it checks the superclass.
If you move include Bipedal
into the Person
class then it will work the way you expect because Boy
does not include a module directly, so it will eventually search the superclass where it will find the defined method.
There may be other creative ways you can accomplish this goal, like the Boy.superclass...
example you gave, but you asked if it's possible to change the lookup behavior when calling super
and the answer is no per the documentation.
No, there is no standard way to force a call to super
to walk the ancestors in a specific order. They are walked in a pre-defined order. Take a look at the documentation on calling methods:
When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.
Here is the order of method lookup for the receiver's class or module
R
:
- The prepended modules of
R
in reverse order
- For a matching method in
R
- The included modules of
R
in reverse order
If
R
is a class with a superclass, this is repeated withR
's superclass until a method is found.
Once a match is found method lookup stops.
Since your class Boy
includes the module Bipedal
directly, and since included modules are searched before the superclass, and since searching stops once a match is found, the superclass Person
is never checked.
The same is true when using refinements because the lookup always hits included modules before it checks the superclass.
If you move include Bipedal
into the Person
class then it will work the way you expect because Boy
does not include a module directly, so it will eventually search the superclass where it will find the defined method.
There may be other creative ways you can accomplish this goal, like the Boy.superclass...
example you gave, but you asked if it's possible to change the lookup behavior when calling super
and the answer is no per the documentation.
edited Nov 27 '18 at 7:50
answered Nov 27 '18 at 3:35
anothermhanothermh
3,37931733
3,37931733
Shame (or not depending how much sanity you like) that you can't editSomeModule.ancestors
.
– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class methodself.ancestors
in the child class with the desired order does not work.super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec forsuper
.
– anothermh
Nov 27 '18 at 19:34
add a comment |
Shame (or not depending how much sanity you like) that you can't editSomeModule.ancestors
.
– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class methodself.ancestors
in the child class with the desired order does not work.super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec forsuper
.
– anothermh
Nov 27 '18 at 19:34
Shame (or not depending how much sanity you like) that you can't edit
SomeModule.ancestors
.– mu is too short
Nov 27 '18 at 7:18
Shame (or not depending how much sanity you like) that you can't edit
SomeModule.ancestors
.– mu is too short
Nov 27 '18 at 7:18
I did a quick test, and defining a class method
self.ancestors
in the child class with the desired order does not work. super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec for super
.– anothermh
Nov 27 '18 at 19:34
I did a quick test, and defining a class method
self.ancestors
in the child class with the desired order does not work. super
must use some other means of looking up the ancestors. You may be able to find some more info in the spec for super
.– anothermh
Nov 27 '18 at 19:34
add a comment |
I don't think you can change how super
works and you can't "super super
" to skip an ancestor but you can use a different ancestor. If you're just including Bipedal
for some of its methods and want to skip a few of them then you could do something like this:
SemiBipedal = Bipedal.dup
SemiBipedal.remove_method(:two_legs)
class Boy < Person
include SemiBipedal
#...
end
Of course johnny.is_a? Bipedal
won't be true anymore and Boy.ancestors
will have SemiBipedal
instead of Bipedal
at index 1 but that might not matter.
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?remove_method
doesn't appear to be private in 2.5.3. You can alwaysSemiBipedal.send(:remove_method, :two_legs)
ormodule SemiBipedal; remove_method :two_legs; end
to kludge around that.
– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and addBipedal.send(:remove_method, :two_legs)
directly toBoy
, assumingBoy
doesn't need theBipedal
version...
– globewalldesk
Nov 28 '18 at 0:21
2
ButBipedal.send(:remove_method, :two_legs)
modifiesBipedal
so everything that uses the module will be affected, hence the copy ofBipedal
(not alias) and removingtwo_legs
from the copy.
– mu is too short
Nov 28 '18 at 0:36
add a comment |
I don't think you can change how super
works and you can't "super super
" to skip an ancestor but you can use a different ancestor. If you're just including Bipedal
for some of its methods and want to skip a few of them then you could do something like this:
SemiBipedal = Bipedal.dup
SemiBipedal.remove_method(:two_legs)
class Boy < Person
include SemiBipedal
#...
end
Of course johnny.is_a? Bipedal
won't be true anymore and Boy.ancestors
will have SemiBipedal
instead of Bipedal
at index 1 but that might not matter.
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?remove_method
doesn't appear to be private in 2.5.3. You can alwaysSemiBipedal.send(:remove_method, :two_legs)
ormodule SemiBipedal; remove_method :two_legs; end
to kludge around that.
– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and addBipedal.send(:remove_method, :two_legs)
directly toBoy
, assumingBoy
doesn't need theBipedal
version...
– globewalldesk
Nov 28 '18 at 0:21
2
ButBipedal.send(:remove_method, :two_legs)
modifiesBipedal
so everything that uses the module will be affected, hence the copy ofBipedal
(not alias) and removingtwo_legs
from the copy.
– mu is too short
Nov 28 '18 at 0:36
add a comment |
I don't think you can change how super
works and you can't "super super
" to skip an ancestor but you can use a different ancestor. If you're just including Bipedal
for some of its methods and want to skip a few of them then you could do something like this:
SemiBipedal = Bipedal.dup
SemiBipedal.remove_method(:two_legs)
class Boy < Person
include SemiBipedal
#...
end
Of course johnny.is_a? Bipedal
won't be true anymore and Boy.ancestors
will have SemiBipedal
instead of Bipedal
at index 1 but that might not matter.
I don't think you can change how super
works and you can't "super super
" to skip an ancestor but you can use a different ancestor. If you're just including Bipedal
for some of its methods and want to skip a few of them then you could do something like this:
SemiBipedal = Bipedal.dup
SemiBipedal.remove_method(:two_legs)
class Boy < Person
include SemiBipedal
#...
end
Of course johnny.is_a? Bipedal
won't be true anymore and Boy.ancestors
will have SemiBipedal
instead of Bipedal
at index 1 but that might not matter.
answered Nov 27 '18 at 7:17
mu is too shortmu is too short
355k58702677
355k58702677
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?remove_method
doesn't appear to be private in 2.5.3. You can alwaysSemiBipedal.send(:remove_method, :two_legs)
ormodule SemiBipedal; remove_method :two_legs; end
to kludge around that.
– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and addBipedal.send(:remove_method, :two_legs)
directly toBoy
, assumingBoy
doesn't need theBipedal
version...
– globewalldesk
Nov 28 '18 at 0:21
2
ButBipedal.send(:remove_method, :two_legs)
modifiesBipedal
so everything that uses the module will be affected, hence the copy ofBipedal
(not alias) and removingtwo_legs
from the copy.
– mu is too short
Nov 28 '18 at 0:36
add a comment |
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?remove_method
doesn't appear to be private in 2.5.3. You can alwaysSemiBipedal.send(:remove_method, :two_legs)
ormodule SemiBipedal; remove_method :two_legs; end
to kludge around that.
– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and addBipedal.send(:remove_method, :two_legs)
directly toBoy
, assumingBoy
doesn't need theBipedal
version...
– globewalldesk
Nov 28 '18 at 0:21
2
ButBipedal.send(:remove_method, :two_legs)
modifiesBipedal
so everything that uses the module will be affected, hence the copy ofBipedal
(not alias) and removingtwo_legs
from the copy.
– mu is too short
Nov 28 '18 at 0:36
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
I love this idea, but when I typed it in, I couldn’t get it to work. I get “private method ‘remove_method’ called for SemiBipedal:Module (NoMethodError)”.
– globewalldesk
Nov 27 '18 at 13:41
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
The only place that remove_method seems to work is within the Bipedal module itself…
– globewalldesk
Nov 27 '18 at 13:51
Which version of Ruby are you using?
remove_method
doesn't appear to be private in 2.5.3. You can always SemiBipedal.send(:remove_method, :two_legs)
or module SemiBipedal; remove_method :two_legs; end
to kludge around that.– mu is too short
Nov 27 '18 at 19:03
Which version of Ruby are you using?
remove_method
doesn't appear to be private in 2.5.3. You can always SemiBipedal.send(:remove_method, :two_legs)
or module SemiBipedal; remove_method :two_legs; end
to kludge around that.– mu is too short
Nov 27 '18 at 19:03
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.
SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and add Bipedal.send(:remove_method, :two_legs)
directly to Boy
, assuming Boy
doesn't need the Bipedal
version...– globewalldesk
Nov 28 '18 at 0:21
I was using 2.4.0 but I updated it to 2.5.3, re-ran the code (copied straight from yours) and it still gives me that private method error.
SemiBipedal.send(:remove_method, :two_legs)
works great. Maybe the most straightforward way is to skip an alias module and add Bipedal.send(:remove_method, :two_legs)
directly to Boy
, assuming Boy
doesn't need the Bipedal
version...– globewalldesk
Nov 28 '18 at 0:21
2
2
But
Bipedal.send(:remove_method, :two_legs)
modifies Bipedal
so everything that uses the module will be affected, hence the copy of Bipedal
(not alias) and removing two_legs
from the copy.– mu is too short
Nov 28 '18 at 0:36
But
Bipedal.send(:remove_method, :two_legs)
modifies Bipedal
so everything that uses the module will be affected, hence the copy of Bipedal
(not alias) and removing two_legs
from the copy.– mu is too short
Nov 28 '18 at 0:36
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53491282%2flet-super-call-the-parent-class-over-an-included-module%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Your use case is not clear. If you want to switch between different methods, why can't they be named as different methods? Why do they have to be named the same? Can you pass some argument to the method, depending on which the method behaves differently?
– sawa
Nov 27 '18 at 7:05
Suppose I am not in charge of the module or the superclass.
– globewalldesk
Nov 27 '18 at 13:59