2012-05-05 7 views
6

Sono programmatore C# nuovo nel linguaggio D. Sono un po 'confuso con OOP in linguaggio di programmazione D.Perché una funzione con modificatore protetto può essere ignorata e accessibile ovunque?

Supponendo che ho la seguente classe:

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

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

Il protected modificatore significa che posso accedere al metodo .foo() proprio sulla classe ereditata, quindi perché questo programma D compila normalmente?

Ecco l'equivalente di 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(); 
    } 
}; 

E non si compila e dato il seguente messaggio di errore (come mi aspettavo):

Test.cs (10 , 30): l'errore CS0507: B.foo()': cannot change access modifiers when overriding protetta 'ereditato membro `A.foo()'

qualcuno può spiegare questo comportamento D? Grazie in anticipo.

+2

Perché sei confuso? C# e D sono solo lingue diverse, quindi fanno le cose in modo diverso. A prima vista, entrambi gli approcci hanno un senso per me, quindi spetta ai progettisti di linguaggio decidere quale strada seguire. – svick

+0

Humm, perché avevo in mente che i modificatori di accesso di un linguaggio di programmazione orientato agli oggetti funzionavano allo stesso modo. – Jack

+0

downvotes- può spiegare per favore? – Jack

risposta

16

Non è utile impedire l'override. La classe derivata potrebbe implementare una funzione di inoltro banale che consente l'accesso. Si consideri:

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

Così, anche se non ha ridefinito il livello di accesso di foo, ho ancora permesso l'accesso del pubblico ad esso e non c'è niente che tu possa fare al riguardo. Permettere la ridefinizione è solo più semplice.

+0

Humm, quindi è il progettista 'D'. Nel linguaggio 'C# .NET', non è possibile scrivere qualcosa come il metodo' call_foo() '. Ha dato un errore 'CS0122: A.foo() 'è inaccessibile a causa del suo livello di protezione. Grazie per la risposta. :) – Jack

+0

@Jack: Cosa, in C# non è possibile scrivere un metodo pubblico che chiama un metodo protetto? – Puppy

+0

No. Non funziona per me, ho provato su C# -Mono e mi è stato fornito il messaggio di errore sopra riportato. – Jack

5

Il comportamento di D in questo corrisponde al comportamento di Java. Una classe derivata può dare alla sua funzione un livello di accesso che è meno restrittivo di quello sulla funzione nella classe base ma non uno che è più restrittivo. Pertanto, una funzione protected può essere sovrascritta come protected o public, ma non può essere sostituita come private e una funzione public può essere sovrascritta come public.

Non ho idea del motivo per cui C# limita lo protected in modo tale che non è possibile sovrascriverlo con una funzione public. Come qualcuno che ha programmato molto in C++, D e Java, ma molto poco in C#, la scelta di C# qui ha poco senso per me. C++, D e Java lo consentono.

7

Perché ci sono alcune grandi risposte alla domanda "perché è possibile?" Penso che C# meriti una spiegazione del perché NON è possibile: si tratta della "filosofia" di un design linguistico e può essere ridotta a uno scontro di "è-a" vs "ha-a".

C++ si basa sul concetto di "has-a", alcuni dei quali sono stati passati a D e Java. B ha il metodofoo e questo è molto importante sia per il compilatore che per il programmatore, non per B. In C++ è persino possibile redeclare un metodo come privato (o ereditare la classe come privato), il che significa che un membro di A NON sarà esposto da B.

C# è hardcore sul concetto di "è-un". Pertanto, poiché qui B in realtà è A, tutto in B deve essere proprio come in A. Né il compilatore né il programmatore devono preoccuparsi delle modifiche, perché non sono possibili modifiche.B è sempre un rimpiazzo perfetto per A.

La filosofia "is-a" impedisce al programma C# di pubblicizzare membri precedentemente protetti, anche se è banale farlo tramite un wrapper pubblico. Non ha molto senso ed è solo un piccolo inconveniente qui - ma è un grosso problema nel mantenere la filosofia della lingua coerente.

Problemi correlati