2012-05-05 27 views
6

Soy un programador de C# nuevo para el lenguaje D. Estoy un poco confundido con OOP en el lenguaje de programación D.¿Por qué una función con modificador protegido puede ser anulada y accesible en todas partes?

Suponiendo que tengo la clase siguiente:

public class A { 
    protected void foo() { 
     writefln("A.foo() called."); 
    } 
}; 

public class B : A { 
    public override void foo() { 
     writefln("B.foo() called."); 
    } 
}; 

El modificador protected significa que puedo tener acceso al método .foo() sólo en clase heredada, ¿por qué este programa D compila normalmente?

Aquí es el equivalente a C# .NET:

using System; 

public class A { 
    protected virtual void foo() { 
     Console.WriteLine("a.foo() called."); 
    } 
}; 

public class B : A { 
    public override void foo() { 
     Console.WriteLine("b.foo() called."); 
    } 
}; 

public class MainClass { 
    public static void Main(string[] args) { 
     A a = new A(); 
     B b = new B();  
     a.foo(); 
     b.foo(); 
    } 
}; 

Que no compila y dado el siguiente mensaje de error (como yo esperaba):

test.cs (10 , 30): error CS0507: B.foo()': cannot change access modifiers when overriding protegida 'heredó el miembro `A.foo()'

¿Puede alguien explicar este comportamiento D? Gracias por adelantado.

+2

¿Por qué estás confundido? C# y D son solo idiomas diferentes, por lo que hacen las cosas de manera diferente. A primera vista, ambos enfoques tienen algún sentido para mí, por lo que depende de los diseñadores del idioma decidir qué camino tomar. – svick

+0

Humm, porque tenía en mente que los modificadores de acceso de un lenguaje de programación orientado a objetos funcionaban de la misma manera. – Jack

+0

downvotes- puede explicar por favor? – Jack

Respuesta

16

No hay propósito en evitar la anulación. La clase derivada podría implementar una función de reenvío trivial que permita el acceso. Considere lo siguiente:

public class A { 
    protected void foo() { 
     writefln("A.foo() called."); 
    } 
}; 

public class B : A { 
    protected override void foo() { // OK 
     writefln("B.foo() called."); 
    } 
    public void call_foo() { 
     foo(); // But I allowed public access anyway! 
    } 
}; 

Por lo tanto, a pesar de que yo no redefinir el nivel de acceso de foo, que todavía se permite el acceso del público a la misma y no hay nada que pueda hacer al respecto. Permitir la redefinición es simplemente más simple.

+0

Humm, entonces es diseñador 'D'. En el lenguaje 'C# .NET', no es posible escribir algo como el método' call_foo() '. Da un 'error CS0122: A.foo() 'es inaccesible debido a su nivel de protección. Gracias por su respuesta. :) – Jack

+0

@Jack: ¿Qué, en C# no puedes escribir un método público que llame a un método protegido? – Puppy

+0

No. No funciona para mí, lo he probado en C# -Mono y aparece el mensaje de error anterior. – Jack

5

El comportamiento de D'D en este juego coincide con el comportamiento de Java. Una clase derivada puede darle a su función un nivel de acceso que es menos restrictivo que el de la función en la clase base, pero no el que es más restrictivo. Por lo tanto, una función protected puede anularse como protected o public, pero no puede anularse como private, y una función public solo puede anularse como public.

No tengo idea de por qué C# restringiría protected de modo que no podría anularlo con una función public. Como alguien que ha programado mucho en C++, D y Java pero muy poco en C#, la elección de C# aquí tiene muy poco sentido para mí. C++, D y Java lo permiten.

7

Porque hay algunas excelentes respuestas a la pregunta "¿por qué es posible?" Creo que C# merece una explicación de por qué NO es posible: se trata de la "filosofía" de un diseño de lenguaje, y se puede resumir en un choque de ideas "es-un" versus "tiene-un".

C++ tiene que ver con el pensamiento "has-a", algo de lo que pasó a D y Java. B tiene método foo y esto es más importante tanto para el compilador como para el programador, no lo que B es. En C++ incluso es posible volver a declarar un método como privado (o heredar clase como privado), lo que significa que un miembro de A NO estará expuesto por B.

C# es un concepto "is-a". Por lo tanto, porque aquí B realmente es A, todo en B debe ser exactamente como en A. Ni el compilador ni el programador tienen que preocuparse por los cambios, porque no hay cambios posibles.B siempre es un reemplazo directo perfecto para A.

La filosofía "is-a" prohíbe que el programa C# publique miembros previamente protegidos, a pesar de que es trivial hacerlo a través de un contenedor público. Tiene poco sentido y es solo un pequeño inconveniente aquí, pero es importante mantener constante la filosofía del lenguaje.

Cuestiones relacionadas