c# - 使いどころ - 基底クラス 派生クラス
Python.NETが派生クラスのメソッドではなく基本メソッドを使用するのはなぜですか? (1)
編集:これは新しいバージョンのpythonnetで修正される予定です( thisプル要求がマージされたとき)。
Python.NETの継承に問題があります。 次のコードで構成されるDLLがあります。
using System;
namespace InheritanceTest
{
public class BaseClass
{
public bool Transmit()
{
throw new NotImplementedException();
}
}
public class InheritedClass: BaseClass
{
public new bool Transmit()
{
Console.WriteLine("Success!");
return true;
}
}
}
InheritedClass
インスタンスのTransmit
メソッドを呼び出してコンソールに書き込み、trueを返し、 BaseClass
のTransmit
メソッドをBaseClass
てBaseClass
をスローするようにします。
次のPythonコードを実行すると:
## setup
import clr
import os
clr.AddReference(os.getcwd() + '\\InheritanceTest.dll')
import InheritanceTest
## method test
base_class = InheritanceTest.BaseClass()
base_class.Transmit() # throws a NotImplementedException as expected
inherited_class = InheritanceTest.InheritedClass()
inherited_class.Transmit() # still throws a NotImplementedException, although it should call InheritedClass.Transmit
私はpythonnetバージョン2.3.0と.NET Framework 4.6.1を使っています。 ご協力いただきありがとうございます!
新しい修飾子は、親クラスの実装ではなく子クラスの実装を使用するようにコンパイラに指示します。 クラスを参照していないが親クラスを参照しているコードでは、親クラスの実装が使用されます。
これは明らかにここでは起こりません。
編集2:これはpythonnetライブラリに関する問題のようです。 この問題は今githubにあります。
pythonnet
メソッドの解像度( methodbinder.cs
ファイルにあるBind
メソッド)は、私見でかなり改善することができます。 とにかく、現時点ではこのメソッドは型階層についてはあまり気にしていません。
単純な解決方法の1つは、 MethodSorter
クラスを変更して、メソッドをソートしてBind
呼び出しで選択されるメソッドを決定するときに派生クラスを優先するようにすることです。
前:
internal class MethodSorter : IComparer
{
int IComparer.Compare(object m1, object m2)
{
int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
if (p1 < p2)
{
return -1;
}
if (p1 > p2)
{
return 1;
}
return 0;
}
}
後:
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)
{
return -1;
}
if (p1 > p2)
{
return 1;
}
return 0;
}
}
注私は詳細なテストを実行していないので、これが他のものを壊さないことを確信できません。 私が言うように、このメソッド全体のバインディングコードは壊れやすいようです。