以某种模糊的方式,一个不添加新功能(但)的派生类的行为与它的基类不同。派生类:
public class MyCheckButton : CheckButton
{
public MyCheckButton(string label) : base(label)
{
}
}
MyCheckButton继承自(GTK#,Mono项目的一部分)CheckButton。但是,在以下代码段中,它们的行为方式不同:
var button1 = new CheckButton("_foo");
var button2 = new MyCheckButton("_foo");
// code omitted
标签中的下划线确保标签获得助记符。对于button1,这适用于我的测试代码:我得到“foo”,其中f加下划线。但是对于button2,这会失败。我只是在对话框中将“_foo”作为标签。
任何人都可以解释一下这个例子中派生类的行为方式可能不同,或者屏幕后面是否有一些可能会检查实际类的类型的魔法?
答案 0 :(得分:7)
[我]屏幕后面有一些魔法可能会检查 实际类的类型?
实际上,有:
public CheckButton(string label) : base(IntPtr.Zero)
{
if (base.GetType() != typeof(CheckButton))
{
ArrayList arrayList = new ArrayList();
ArrayList arrayList2 = new ArrayList();
arrayList2.Add("label");
arrayList.Add(new Value(label));
this.CreateNativeObject((string[])arrayList2.ToArray(typeof(string)), (Value[])arrayList.ToArray(typeof(Value)));
}
else
{
IntPtr intPtr = Marshaller.StringToPtrGStrdup(label);
this.Raw = CheckButton.gtk_check_button_new_with_mnemonic(intPtr);
Marshaller.Free(intPtr);
}
}
看起来你的子类将走向前一条路线。不知道为什么会破坏助记符;后一种方法是本机gtk库上的P / Invoke。在label
对象中包装Value
可能会破坏助记符。
让这成为一个教训(对于GTK#设计师):不要违反Liskov Substitution Principle。这令人困惑!
答案 1 :(得分:2)
这就是为什么,看看CheckButton ctor的来源:
public CheckMenuItem (string label) : base (IntPtr.Zero)
{
if (GetType() != typeof (CheckMenuItem)) {
CreateNativeObject (new string [0], new GLib.Value [0]);
AccelLabel al = new AccelLabel ("");
al.TextWithMnemonic = label;
al.SetAlignment (0.0f, 0.5f);
Add (al);
al.AccelWidget = this;
return;
}
IntPtr native = GLib.Marshaller.StringToPtrGStrdup (label);
Raw = gtk_check_menu_item_new_with_mnemonic (native);
GLib.Marshaller.Free (native);
}
派生类型与.ctor
中的CheckButton不遵循相同的代码路径