2011-07-12 8 views
7

De alguna manera oscura, una clase derivada que no agrega nuevas funcionalidades (aún) se comporta de forma diferente a su clase base. La clase derivada:¿Por qué esta clase derivada se comporta diferente de su clase base?

public class MyCheckButton : CheckButton 
{ 
    public MyCheckButton(string label) : base(label) 
    { 
    } 
} 

MyCheckButton hereda de un (GTK #, parte del proyecto Mono) CheckButton. Sin embargo, en el siguiente fragmento de código que se comportan de manera diferente:

var button1 = new CheckButton("_foo"); 
var button2 = new MyCheckButton("_foo"); 
// code omitted 

El subrayado en la etiqueta se asegura de que la etiqueta consigue un mnemónico. Para button1 esto funciona en mi testcode: obtengo "foo" donde f está subrayado. Sin embargo, para button2 esto falla. Acabo de obtener "_foo" como una etiqueta en mi cuadro de diálogo.

¿Alguien puede explicar cómo la clase derivada en este ejemplo podría comportarse de manera diferente o hay algo mágico detrás de la pantalla que tal vez verifique el tipo de la clase real?

+3

¿Es este código de MyCheckButton está todo presentado aquí ? – Tigran

+2

¿Qué sucede si no agrega button1? Tal vez no le gustan dos 'f' mnemotécnicos? – dlev

+0

Sí, este es todo el código. Hice el ejemplo lo más simple posible. Los dos mismos mnemotécnicos no son el problema. Lo he intentado. –

Respuesta

7

[I] s hay algo mágico detrás de la pantalla que tal vez comprueba el tipo de la clase real?

En realidad, hay:

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

Parece que a la subclase se va de la ruta anterior. Sin embargo, no estoy seguro de por qué eso estropearía el mnemónico; el último método es una P/Invoke en la biblioteca nativa gtk. Es posible que envolver label en un objeto Value esté arruinando las cosas mnemotécnicas.

Que sea una lección (para los diseñadores de GTK #): no infrinjan el Liskov Substitution Principle. ¡Es confuso!

+0

El mnemónico desaparece en la ruta anterior porque la propiedad "usar-subrayar" del botón no está configurada en True, ya que está en el constructor 'gtk_check_button_new_with_mnemonic()' nativo. Un "subrayado de uso", el par verdadero debe agregarse a las listas de arreglos. Esta no es una violación deliberada del principio de sustitución, es un error y debe informarse en http://www.mono-project.com/Bugs. – ptomato

+0

He enviado un informe de error. –

2

He aquí por qué, mira a la fuente de la 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); 
} 

Derivado tipos no siguen la misma ruta de código como CheckButton en el .ctor

Cuestiones relacionadas