48 votes

Interne de la classe abstraite: comment masquer utilisation à l'extérieur de l'assemblage?

J'ai une assemblée commune/projet qui a une classe de base abstraite, puis plusieurs classes dérivées qui je veux rendre public, pour d'autres assemblées.

Je ne veux pas la classe de base abstraite pour apparaître dans ces autres assemblées dans Intellisense, alors j'ai pensé que je voudrais faire c' internal, mais j'ai cette erreur:

Incompatible accessibilité: la classe de base 'Paramètres' est moins accessible que la classe de IrcSettings' ....

Je n'ai pas vraiment l'obtenir. Je suis obligé de faire de l'abstrait Settings classe public, et donc visible à l'extérieur de cette assemblée.

Comment puis-je faire de cette classe internal à la place?

89voto

Rex M Points 80372

Si je comprends bien, vous voulez que votre classe abstraite pour être mis en œuvre par d'autres classes de la même assemblée (par exemple, il est interne), mais les classes dérivées pourrait être publique.

La manière de faire cela est de faire de la classe de base abstraite public, mais également lui donner un interne constructeur par défaut:

public abstract class MyClass
{
    internal MyClass() { }
}

Cela permettra MyClass (et donc de ses membres) pour être visible et utilisable à des cours à l'extérieur de votre assemblée, mais les classes à l'extérieur de votre assemblée ne peut pas hériter d'elle (obtiendrez une erreur de compilation).

Edit: Si des classes qui peut être vu par l'extérieur des assemblées hériter de Maclasse, vous ne pouvez pas empêcher MyClass d'être vu - par exemple, en montrant dans Intellisense. Toutefois, vous pouvez les empêcher d'être utilisé par la suite de la ci-dessus.

9voto

thecoop Points 23695

La classe de base abstraite doit être publique, comme l'ensemble de la hiérarchie d'héritage de classe doit être visible. Cela garantit le polymorphisme fonctionne et est valide; cependant, toutes les classes de base " les membres peuvent être internes (y compris le constructeur), et n'est donc pas utilisable en dehors de votre assemblée

6voto

Chris Marisic Points 11495

Il n'y a vraiment pas beaucoup d'un avantage à ce que vous essayez d'atteindre, mais de ce que vous êtes réellement à la recherche à réaliser est semblable à cela.

Votre classe de base abstraite dans 1 assemblée avec tout intérieur. Dans le AssemblyInfo pour cette assemblée, vous devez ajouter

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

Puis dans une autre assemblée, vous avez toutes les classes que vous souhaitez la disposition du public. Remarque vous serez toujours en mesure d'accéder à la classe de base de intellisense pour le code à l'intérieur de cs_friend_assemblies_2 ou ce que vous nommez votre assemblée, mais pas n'importe où ailleurs.

4voto

LBushkin Points 60611

Vous ne pouvez pas simultanément de faire la classe à la disposition des autres assemblées de l'héritage, mais aussi privées de sorte qu'il ne peut pas être visible pour les autres consommateurs. Vous pouvez faire la classe interne, et de l'exposer à un montage spécifique (si c'est un ami de l'assemblée) à l'aide de l' [InternalsVisibleTo] d'attribut, mais je ne pense pas que ce est ce que vous voulez.

Si vous voulez garder le code (autres que les classes dérivées) d'être en mesure d'instancier votre classe de base, vous pouvez lui donner un protégé constructeur:

abstract class MyBaseClass
{
    protected MyBaseClass() { ... } // only inheritors can access this...
}

Vous pouvez masquer les membres de la classe à partir d'Intellisense à l'aide de l' EditorBrowsable d'attribut:

abstract class MyBaseClass
{ 
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public void SomeMethodToBeHidden() { }
}

Il convient de noter que certaines personnes ont signalé des problèmes avec l'IDE pas toujours dans le respect de cet attribut.

1voto

Joel B Fant Points 14013

Pour autant que je suis concerné, c'est un non-problème. Observer:

public abstract class Foo {
    public void virtual Bar() {
        // default implementation
    }
}

public class NormalFoo : Foo { }

public class SpecialFoo : Foo {
    public override void Bar() {
        // special implementation
    }
}

var foolist = new List<Foo>();

foolist.Add( new NormalFoo() );
foolist.Add( new SpecialFoo() );

foreach (var f in foolist) {
    f.Bar();
}

Le ci-dessus ne fonctionne pas à tous les sans polymorphisme -- être capable de se référer à des instances de différentes classes dérivées par le biais de leur interface commune, la classe de base abstraite. Ce que vous voulez faire est de prendre que loin et de paralyser la facilité d'utilisation de votre hiérarchie de classe. Je ne pense pas que tu devrais continuer dans cette voie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X