2010-10-25 3 views
3

Voici un exemple. J'ai deux classes, un héritage, et les deux ont une fonction avec le même nom, mais différents arguments:Comment créer une méthode ou une propriété en C# publique, mais non héritable?

public class MyClass 
{ 
    //public class members 

    public MyClass() 
    { 
     //constructor code 
    } 

    public void Copy(MyClass classToCopy) 
    { 
     //copy code 
    } 
} 

public class InheritedClass : MyClass 
{ 
    //public class members 

    public InheritedClass():base() 
    { 
     //constructor code 
    } 

    public void Copy(InheritedClass inheritedClassToCopy) 
    { 
     //copy code 
    } 
} 

Ma question est de savoir comment puis-je faire la classe de base méthode de copie (MyClass.Copy) non héritables ou non visible dans InheritedClass? Je ne veux pas être en mesure de le faire:

MyClass a; 
InheritedClass b; 
b.Copy(a); 

Est-ce que cela a du sens, ou devrais-je garder cette fonctionnalité là-dedans? Ce que je demande peut-il même être fait?

Répondre

22

Est-ce que cela a du sens, ou devrais-je garder cette fonctionnalité là-dedans? Ce que je demande peut-il même être fait?

Essayer de masquer une méthode publique comme celle-ci lorsqu'elle est utilisée par une classe de base est problématique. Vous essayez intentionnellement de violer le Liskov substitution principle.

alt text

+0

Ok, je ne l'avais jamais vu auparavant. C'est logique. –

+11

J'espère que cela ne vous dérange pas que j'ai ajouté l'affiche motivateur;) – jgauffin

+0

@jgauffin: Lol ... –

6

Vous ne pouvez pas faire ce que vous voulez faire ici; C# n'autorise pas la variance négative dans les membres hérités. (En réalité, il n'y a presque pas de langues)

Il se peut cependant que vous ne souhaitiez pas du tout une classe héritée; ce que vous voulez vraiment, c'est une interface. Ou ... vos deux classes ici peuvent ne pas avoir la relation correcte; peut-être qu'ils devraient tous les deux être des frères et soeurs communs d'une troisième classe, qui est leur parent.

4

Vous pouvez utiliser une implémentation d'interface explicite pour masquer cette méthode à l'héritier. Mais vous devez ajouter une interface bien sûr et vous aurez besoin de lancer votre type à l'interface pour appeler votre méthode:

public interface MyInterface 
{ 
    void Copy(MyClass classToCopy) 
} 

public class MyClass : MyInterface 
{ 
    void MyInterface.Copy(MyClass classToCopy) 
    { 
     //copy code 
    } 
} 
+0

+1, pourrait bien répondre à l'exigence ultime de l'OP avec un peu de refactoring. –

2

Ce n'est pas possible. Une classe héritée hérite de tous les membres, méthodes et propriétés publics et protégés. Utiliser le modificateur sealed pour le rendre non-redéfinissable, mais toujours accessible à votre classe héritée.

1

Ce que tout le monde a dit, mais si je déduis correctement votre objectif, c'est de m'assurer que les utilisateurs de InheritedClass n'utilisent jamais la méthode MyClass. Dans ce cas, excluez-le de MyClass et créez deux classes qui l'héritent.

Rendre abstrait MyBaseClass s'il ne doit pas être instancié (très probablement).

(Edité - vous probablement vouloir inclure le code de copie pour tout ce qui fait partie de la classe de base dans la classe de base)

public abstract class MyBaseClass 
{ 
    public MyClass() 
    { 
     //constructor code 
    } 
    protected void Copy(MyBaseClass classToCopy) 
    { 
     //copy code 
    } 
    // other methods that all inherited classes can use 
} 

public class MyClass: MyBaseClass 
{ 
    public MyClass():base() 
    { 
     //constructor code 
    } 
    public void Copy(MyClass myClassToCopy) 
    { 
     base.Copy(myClassToCopy); 
     //specific copy code for this extensions in this class 
    } 
} 

public class InheritedClass : MyBaseClass 
{ 
    public InheritedClass():base() 
    { 
     //constructor code 
    } 
    public void Copy(InheritedClass inheritedClassToCopy) 
    { 
     base.Copy(myClassToCopy); 
     //specific copy code for this extensions in this class 
    } 
} 
+0

@jamietre: Y a-t-il un moyen d'avoir deux ou plusieurs classes publiques qui héritent d'un ancêtre commun, sans permettre au code extérieur de dériver des classes de cet ancêtre commun?Par exemple, si la classe de base est supposée être pour des objets immuables, et que les seules classes qui en dérivent sont sémantiquement immuables, tout est bon. Mais si la classe de base peut être dérivée via un code externe, le code externe pourrait créer un objet "immuable" mutable. – supercat

+0

@supercat: Vous pouvez utiliser un constructeur 'internal'. –

+0

Je ne suis pas exactement sûr de comprendre la situation que vous essayez d'éviter. Si la classe de base est marquée comme abstraite, vous pouvez créer des classes qui l'héritent, mais vous ne pouvez pas créer une instance de la classe de base. Cela signifie que vous pouvez créer du code qui accepte les polymporhps de BaseClass même si aucune entité telle que BaseClass ne peut être créée. Si vous essayez de cacher la classe abstraite d'un autre code, vous ne pouvez pas le faire, car vous ne pourrez alors pas utiliser la classe de base comme type polymorphe pour les procédures qui devraient pouvoir utiliser des classes héritées. Quel est le point de l'héritage. –

Questions connexes