90 votes

Remplacer get, mais pas set

J'ai une classe abstraite qui définit une get mais pas set car, en ce qui concerne cette classe abstraite, elle n'a besoin que d'un fichier get .

public abstract BaseClass
{
  public abstract double MyPop
  {get;}
}

Cependant, dans certaines classes dérivées, j'ai besoin d'une fonction set donc je regarde cette implémentation

public class DClass: BaseClass
{
  public override double MyPop
  {get;set;}
}

Le problème est que j'ai obtenu une erreur de compilation, disant que

*.set : ne peut pas être surchargé car *. n'a pas d'accesseur set surchargé.

Même si je pense que la syntaxe ci-dessus est parfaitement légitime.

Une idée à ce sujet ? Une solution de contournement ou la raison de cette situation ?

Edit : La seule approche à laquelle je pense est de mettre les deux get y set comme dans la classe abstraite, et laisser la sous-classe lancer un NotImplementedException si set est appelé et ce n'est pas nécessaire. C'est quelque chose que je n'aime pas, de même qu'un méthode spéciale de réglage .

0 votes

Décomposons un peu. Vous devez construire un ensemble de classes qui exposent une méthode de lecture d'un fichier double qui sera mise en œuvre spécifiquement dans chaque classe. Parfois, cette valeur devra être définie, et donc certaines de ces classes devraient exposer un moyen de la définir. Est-ce bien le cas ? Combien de niveaux d'héritage devez-vous utiliser ?

1 votes

@Codesleuth : oui. Quant au nombre de niveaux d'héritage, je ne vois pas en quoi cela est pertinent pour la question ?

0 votes

David, ironiquement, cela ressemble à une question à laquelle je ne veux pas accepter de réponse.

28voto

David M Points 45808

Une réponse possible serait de remplacer le getter, puis d'implémenter une méthode setter séparée. Si vous ne voulez pas que le setter de la propriété soit défini dans la base, vous n'avez pas beaucoup d'autres options.

public override double MyPop
{
    get { return _myPop; }
}

public void SetMyPop(double value)
{
    _myPop = value;
}

17voto

Laurent Etiemble Points 17360

Il n'est pas possible de faire ce que vous voulez. Vous devez définir le setter dans la propriété abstraite, sinon vous ne pourrez pas le remplacer correctement.

Le seul cas que je connaisse où un getter est défini et où un getter/setter est implémenté est l'utilisation d'une interface :

public interface IBaseInterface
{
    double MyPop { get; }
}

public class DClass : IBaseInterface
{
    public double MyPop { get; set; }
}

13 votes

Ce n'est pas une mauvaise approche, mais parfois, il suffit d'utiliser une classe abstraite, et non une interface.

0 votes

La préoccupation de Graviton est partiellement atténuée par C# 8, qui introduit Méthodes d'interface par défaut .

9voto

herzmeister Points 7077

Si BaseClass est dans votre propre codebase, alors vous pouvez le faire :

abstract public class BaseClass
{
    abstract public double MyPop { get; protected set; }
}

public class DClass : BaseClass
{
    private double _myProp;
    public override double MyProp
    {
        get { return _myProp; }
        protected set { _myProp = value; }
    }
}

EDIT : Vous pouvez ensuite créer une méthode publique dans la DClass. SetMyProp(double myProp) ou autre. La conception de la classe pour votre modèle de domaine doit être claire ou parler d'elle-même pour expliquer pourquoi vous ne pouvez pas définir la propriété directement dans la classe de base et pourquoi vous pouvez le faire dans la classe dérivée.

0 votes

D'accord, mais qu'en est-il des sous-classes qui n'ont pas besoin de définir l'attribut MyPop ?

0 votes

Peut-être ne peuvent-ils dériver que de BaseClass et non de DClass ?

0 votes

Je ne pense pas que ce soit une bonne idée pour mes applications ; l'héritage devrait être réservé à des applications de type is a et non pas pour contourner une limitation du langage ; d'ailleurs, j'utilise l'héritage à d'autres fins plus réalistes dans l'application ici.

5voto

mattjames Points 898

Êtes-vous sûr que ce que vous essayez de faire serait une bonne conception si vous trouviez un moyen de le faire ?

Cela permettrait aux objets de la sous-classe d'effectuer des changements d'état que les objets de la classe mère ne peuvent pas faire. Cela ne violerait-il pas le principe de substitution de Liskov ?

2voto

Siege Points 1819

Vous pourriez faire quelque chose comme ça :

abstract class TestBase { public abstract int Int { get; } }

`class TestDerivedHelper : TestBase { private int _Int; public override int Int { get { return _Int; } }

    protected void SetInt(int value)
    {
        this._Int = value;
    }
}

class TestDerived : TestDerivedHelper
{
    public new int Int
    {
        get { return base.Int; }
        set { base.SetInt(value); }
    }
}` 

En utilisant TestDerived, vous obtiendrez la fonctionnalité que vous recherchez. Le seul inconvénient que je vois à cette méthode est que vous devez implémenter chaque méthode abstraite de TestDerivedHelper, mais cela vous donne plus de contrôle par la suite.

J'espère que cela vous aidera ;)

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