Il new
modifier causa l'occultamento del membro, che interrompe la relazione polimorfica nella gerarchia di classi. Il metodo SayHi
di B
viene considerato come distinto (non un override) da A
's (quindi la scelta della parola "nuovo" come parola chiave). Il metodo C
sostituisce quindi lo B
e non lo A
(che rimane nascosto).
Pertanto, quando si chiama SayHi
in un'istanza C
attraverso un riferimento A
, il runtime risolverebbe contro il tipo A
, non il tipo C
(entro cui SayHi
è un metodo “nuovo” ereditato da B
).
Se, d'altra parte, si dovesse eseguire:
B p = new C();
p.SayHi();
... si otterrebbe il risultato polimorfico atteso:
From C
Edit: Poiché è stata richiesta un caso d'uso ecco uno. Prima dell'introduzione dei generici in .NET Framework 2.0, l'occultamento dei membri veniva talvolta usato come mezzo per alterare i tipi di ritorno dei metodi ereditati nelle classi derivate (cosa che non è possibile fare quando si esegue l'override) per restituire tipi più specifici. Per esempio:
class ObjectContainer
{
private object item;
public object Item
{
get { return item; }
set { item = value; }
}
}
class StringContainer : ObjectContainer
{
public new virtual string Item
{
get { return base.Item as string; }
set { base.Item = value as string; }
}
}
class QuotedStringContainer : StringContainer
{
public override string Item
{
get { return "\"" + base.Item + "\""; }
}
}
La Item
proprietà della classe ObjectContainer
restituisce una pianura object
. Tuttavia, in StringContainer
, questa proprietà ereditata è nascosta per restituire invece string
. Così:
ObjectContainer oc = new StringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since StringContainer.Item is now resolved
La classe QuotedStringContainer
ignora la proprietà di StringContainer
, ereditando il suo tipo di ritorno string
Item
; tuttavia, è ancora nascosto dallo object
-ritorno a Item
proprietà di ObjectContainer
. Se non fosse così, non ci sarebbe modo di conciliare i loro tipi restituiti disparati ...
ObjectContainer oc = new QuotedStringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
// (polymorphism!)
string s3 = ((QuotedStringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
'new' da' B' si nasconde il sovraccarico virtuale in 'C'. Cambia 'p' per digitare' B' e vedrai l'output da 'C' – asawyer
La domanda è" a che serve questo? " ma la vera domanda è "perché fa questo?". Sono curioso di sapere che il caso d'uso per questo è: sconfiggere intenzionalmente l'ereditarietà in un modo non ovvio per i consumatori della tua API sembra incredibilmente pericoloso. – Chuu
@ Chuu: Grazie, ho chiarito. – dotancohen