How to Pick The Method to Call When There Is Mixin Method Name Conflict

How to resolve ruby module/mixin method conflict

The problem for you is that there is no multiple inheritance in Ruby; so the modules get inserted as an ancestor one above the other, and as such F#initialize overshadows E#initialize. As you found, it is easy to access F#initialize using super(f); but the other one needs a hack to access: we can pick the initialize method directly off of the module, because it is an ancestor; then bind it to the current object and run it.

def initialize(e, f)
E.instance_method(:initialize).bind(self).call(e)
F.instance_method(:initialize).bind(self).call(f) # equivalent to super(f)
end

However, I do not recommend this. If you need to run several initialisers, you'd be better off using composition, rather than inheritance (and to be clear, include is inheritance).

ruby include method name collision

I assume the real question is: how do I ensure that the my modules are not using other modules methods, which (which accidentally have the same name).

It's best if you can make sure that your module methods are not state dependent and define them as module method and use them this way. So you explicitly use any helping methods like this:

module C
def c
puts C.collision
end
def self.collision
'c'
end
end

module B
def b
puts B.collision
end
def self.collision
'b'
end
end

class A
include B
include C
end

A.new.b # b
A.new.c # c

If you want to make them private, there's some extra code to put there, you can read a clear article about it: https://6ftdan.com/allyourdev/2015/05/02/private-module-methods-in-ruby/

As stated in this answer there's not magic you can turn on to make it work. Include mechanism is quite simple and (IMO) it should stay that way. As you are aware of this collision problem - you can now avoid it.

In case you don't like this approach, you can also encapsulate the real work in a class and use module just for inclusion:

  module C
def c
MyLibStuff::ClassDoingRealWork.no_collision_here_anymore(any, param, if_needed)
end
end

In Dart, how can I call a superclass method shadowed by a mixin method?

The mixin method from C shadows the method from B, so you can't use super directly to refer to the B method. You need to introduce a way to access it.

What you can do is to put a private redirecting function in between the B class and the C mixin application:

class A extends B with _Helper, C {
int getValue() {
// It's C
super.getValue();
// Now I want to get B's getValue how do it?
return super._getValueFromB();
}
}

class B {
int getValue() {
return 1;
}
}
mixin C {
int getValue() {
return 2;
}
}
mixin _Helper on B {
int _getValueFromB() => super.getValue();
}

Since the mixin application order is B, B-with-_Helper, B-with-_Helper-with-C, the super of the B-with-_Helper superclass is B, and the _getValueFromB will access it correctly.

Ruby: Module, Mixins and Blocks confusing?

By the way: in Ruby 2.0, there are two features which help you with both your problems.

Module#prepend prepends a mixin to the inheritance chain, so that methods defined in the mixin override methods defined in the module/class it is being mixed into.

Refinements allow lexically scoped monkeypatching.

Here they are in action (you can get a current build of YARV 2.0 via RVM or ruby-build easily):

module Sum
def sum(initial=0)
inject(initial, :+)
end
end

module ArrayWithSum
refine Array do
prepend Sum
end
end

class Foo
using ArrayWithSum

p [1, 2, 3].sum
# 6
end

p [1, 2, 3].sum
# NoMethodError: undefined method `sum' for [1, 2, 3]:Array

using ArrayWithSum
p [1, 2, 3].sum
# 6

Ruby mixins and calling super methods

You can use this:

super if defined?(super)

Here is an example:

class A
end

class B < A
def t
super if defined?(super)
puts "Hi from B"
end
end

B.new.t

How can I call a function from a method of the same name?

A couple of different ways to resolve the name conflict:

  • As Christopher Moore mentioned, you can explicitly import dart:core with a prefix. Note that if you don't want to prefix everything from dart:core, you could import it twice, once into the global namespace and again into the prefixed namespace:

    import 'dart:core';
    import 'dart:core' as core;

    Then you would be able to explicitly use core.print within your print method and use print normally everywhere else.

    Note that if you have a method trying to call a global function with the same name within the same Dart library, you could split your code into multiple files, or your library could import itself with a prefix:

    foo.dart:

    import 'foo.dart' as foo;

    class SomeClass {
    void f() => foo.f();
    }

    void f() {
    // Do stuff.
    }
  • You alternatively could explicitly create another reference to the normal print function with a different name:

    final _print = print;

    class A {
    String val;
    void print() {
    _print(val);
    }
    }

How to mixin some class methods and some instance methods from a module in Ruby?

This pattern is very common in Ruby. So common, in fact, that ActiveSupport::Concern abstracts it a bit.

Your typical implementation looks like this:

module Foo
def self.included(other_mod)
other_mod.extend ClassMethods
end

def instance_method
end

module ClassMethods
def class_method
end
end
end

class Bar
include Foo
end

You can't accomplish this easily as you describe without somehow splitting the included module into multiple pieces, though, unfortunately.

Mixins and duplicate methods in React.js

Yes, it's intentional, and the main factor that makes mixins very powerful in React.

So what happens is:

  • for the 'component...' functions, they're called in the order of mixin[0], mixins[1], ..., component
  • propTypes, and the return value of getInitialState and getDefaultProps are merged
  • other conflicting method names, or conflicts while merging the above results in an error


Related Topics



Leave a reply



Submit