diff --git a/AUTHORS.md b/AUTHORS.md index bd1aa4148..fe2d2b172 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -42,6 +42,7 @@ - Sam Winstanley ([@swinstanley](https://github.com/swinstanley)) - Sean Freitag ([@cowboygneox](https://github.com/cowboygneox)) - Serge Weinstock ([@sweinst](https://github.com/sweinst)) +- Simon Mourier ([@smourier](https://github.com/smourier)) - Viktoria Kovescses ([@vkovec](https://github.com/vkovec)) - Ville M. Vainio ([@vivainio](https://github.com/vivainio)) - Virgil Dupras ([@hsoft](https://github.com/hsoft)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63e00be98..55d776ae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Fixed errors breaking .NET Remoting on method invoke ([#276][i276]) - Fixed PyObject.GetHashCode ([#676][i676]) - Fix memory leaks due to spurious handle incrementation ([#691][i691]) +- Fix inheritance of non-abstract base methods ([#755][i755]) ## [2.3.0][] - 2017-03-11 @@ -691,3 +692,4 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. [p625]: https://github.com/pythonnet/pythonnet/pull/625 [i131]: https://github.com/pythonnet/pythonnet/issues/131 [p531]: https://github.com/pythonnet/pythonnet/pull/531 +[i755]: https://github.com/pythonnet/pythonnet/pull/755 diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index fac117f5c..5e800c36f 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -601,6 +601,19 @@ internal class MethodSorter : IComparer { int IComparer.Compare(object m1, object m2) { + var me1 = (MethodBase)m1; + var me2 = (MethodBase)m2; + if (me1.DeclaringType != me2.DeclaringType) + { + // m2's type derives from m1's type, favor m2 + if (me1.DeclaringType.IsAssignableFrom(me2.DeclaringType)) + return 1; + + // m1's type derives from m2's type, favor m1 + if (me2.DeclaringType.IsAssignableFrom(me1.DeclaringType)) + return -1; + } + int p1 = MethodBinder.GetPrecedence((MethodBase)m1); int p2 = MethodBinder.GetPrecedence((MethodBase)m2); if (p1 < p2) diff --git a/src/testing/InheritanceTest.cs b/src/testing/InheritanceTest.cs new file mode 100644 index 000000000..529703b3c --- /dev/null +++ b/src/testing/InheritanceTest.cs @@ -0,0 +1,14 @@ +using System; + +namespace Python.Test +{ + public class BaseClass + { + public bool IsBase() => true; + } + + public class DerivedClass : BaseClass + { + public new bool IsBase() => false; + } +} diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj index 8a8d9ed2b..b9a250817 100644 --- a/src/testing/Python.Test.csproj +++ b/src/testing/Python.Test.csproj @@ -1,4 +1,4 @@ - + Debug @@ -83,6 +83,7 @@ + @@ -110,4 +111,4 @@ - + \ No newline at end of file diff --git a/src/tests/test_class.py b/src/tests/test_class.py index 68773508b..612ce442e 100644 --- a/src/tests/test_class.py +++ b/src/tests/test_class.py @@ -281,3 +281,14 @@ def PyCallback(self, self2): testobj.DoCallback() assert testobj.PyCallbackWasCalled assert testobj.SameReference + + +def test_method_inheritance(): + """Ensure that we call the overridden method instead of the one provided in + the base class.""" + + base = Test.BaseClass() + derived = Test.DerivedClass() + + assert base.IsBase() == True + assert derived.IsBase() == False