2011-05-18 1 views
3

S'il vous plaît considérer la conception suivante:propriété scellé de la classe abstraite

public interface IBook 
{ 
    string Author { get; set; } 

    string Title { get; set; } 
} 

abstract class BaseBook : IBook 
{ 
    private string _title; 

    public virtual string Author 
    { 
     get 
     { 
      Console.WriteLine("Base book GET!"); 
      return _title; 
     } 
     set 
     { 
      Console.WriteLine("Base book SET!"); 
      _title = value; 
     } 
    } 

    public string Title { get; set; } 
} 

class Book : BaseBook 
{ 
} 

class SuperBook : Book 
{ 
    public override string Author 
    { 
     get 
     { 
      Console.WriteLine("SuperBook GET!"); 
      return base.Author; 
     } 
     set 
     { 
      Console.WriteLine("SuperBook SET!"); 
      base.Author = value; 
     } 
    } 

    public string Title { get; set; } 
} 

Est-il possible rendre la propriété Title de la classe de base BaseBookscellée pour empêcher la propriété d'être substituée dans les classes dérivées (comme les classes Book et SuperBook)?

+0

Et pourquoi voudriez-vous une telle chose? Y at-il une raison particulière pour laquelle un utilisateur ne devrait pas être autorisé à remplacer votre propriété? –

Répondre

2

Si vous compilez votre programme, vous recevrez l'avertissement suivant:

prog.cs (63,19): avertissement CS0108: SuperBook.Title' hides inherited member BaseBook.Title ». Utilisez le nouveau mot-clé se cacher était destiné

Cela signifie que votre SuperBook.Title se cache le titre de BaseBook. Le masquage est différent du remplacement, car le membre n'est pas virtuel. Qu'est-ce qui se passe avec la dissimulation est la suivante: si le compilateur traite votre objet comme une instance de la classe SuperBook, il appellera la méthode SuperBook.Title. Si, cependant, le compilateur traite votre instance en tant que classe BaseBook, l'appel sera effectué à BaseBook.Title.

Par exemple:

SuperBook b1 = new SuperBook(); 
Console.Writeline(b1.Title); // will result in a call to SuperBook.Title 
BaseBook b2 = b1; 
Console.Writeline(b1.Title); // will result in a call to BaseBook.Title 

Si vous faites sera toujours appelée la propriété virtuelle, alors le résultat est que la mise en œuvre la plus dérivée, parce que le compilateur utilise une table virtuelle pour trouver la méthode à appeler. Enfin, si vous voulez que la propriété soit virtuelle pour que chaque appel soit résolu en SuperBook.Title, mais que vous ne souhaitiez pas que l'utilisateur le remplace sur d'autres classes dérivées, tout ce que vous avez à faire est de marquer la propriété sealed override.

3

Si ce n'est pas virtuel, il ne peut pas être remplacé, il peut seulement être caché (en utilisant le mot-clé new). Contrairement à Java, les méthodes C# (et par propriétés d'extension) ne sont pas implicitement virtuelles, mais plutôt explicitement.

1

Vous ne pourrez pas remplacer la propriété Title à moins qu'elle ne soit marquée virtual de toute façon. Ce que vous ne pouvez pas empêcher est caché par quelqu'un utilisant l'opérateur new.

+0

Oui, vous avez raison: 'Ce que vous ne pouvez pas empêcher est caché par quelqu'un utilisant le nouvel opérateur. '. –

1

Vous ne pouvez déjà pas remplacer BaseBook.Title. SuperBook.Title cache en réalité BaseBook.Title plutôt que de le remplacer. Il devrait vraiment avoir le nouveau mot-clé dessus si la dissimulation était prévue; en fait, vous obtiendrez un avertissement du compilateur à cet effet.

-3

Utilisez le mot clé "sealed" sur votre propriété Title.

+0

Cela ne fonctionnera pas car Title n'est pas virtuel et ne peut donc pas être scellé. – Gal

Questions connexes