Почему этот производный класс отличается от своего базового класса - PullRequest
7 голосов
/ 12 июля 2011

В некотором неясном смысле производный класс, который не добавляет новых функций (пока), ведет себя не так, как его базовый класс. Производный класс:

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" в своем диалоге.

Может кто-нибудь объяснить, как производный класс в этом примере может вести себя по-другому, или за экраном происходит какое-то волшебство, которое может проверять тип фактического класса?

Ответы [ 2 ]

7 голосов
/ 13 июля 2011

[Есть] какое-то волшебство происходит за экраном, который может проверять тип фактического класса?

На самом деле, есть:

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);
    }
}

Похоже, ваш подкласс будет идти по прежнему маршруту.Не уверен, почему это испортит мнемонику, хотя;последний метод - это P / Invoke в собственной библиотеке gtk.Возможно, что обертка label в Value объекте запутывает мнемонические вещи.

Пусть это будет уроком (для разработчиков GTK #): не нарушайте принцип подстановки Liskov.Это сбивает с толку!

2 голосов
/ 13 июля 2011

Вот почему, посмотрите на источник для ctor CheckButton:

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);
}

Производные типы не следуют тому же пути кода, что и CheckButton в .ctor

...