C'est possible
tl; dr - Vous pouvez remplacer une méthode get-only avec un setter si vous le souhaitez. C'est fondamentalement juste:
Créez une newpropriété qui a à la fois un getet un en setutilisant le même nom.
Si vous ne faites rien d'autre, l'ancienne getméthode sera toujours appelée lorsque la classe dérivée sera appelée via son type de base. Pour résoudre ce problème, ajoutez une abstractcouche intermédiaire qui utilise overridel'ancienne getméthode pour la forcer à renvoyer le getrésultat de la nouvelle méthode.
Cela nous permet de remplacer les propriétés par get/ setmême s'il en manquait un dans leur définition de base.
En prime, vous pouvez également modifier le type de retour si vous le souhaitez.
Si la définition de base était get-only, vous pouvez utiliser un type de retour plus dérivé.
Si la définition de base était set-only, vous pouvez utiliser un type de retour moins dérivé.
Si la définition de base était déjà get/ set, alors:
Dans tous les cas, vous pouvez conserver le même type de retour si vous le souhaitez. Les exemples ci-dessous utilisent le même type de retour pour plus de simplicité.
Situation: getpropriété préexistante uniquement
Vous avez une structure de classe que vous ne pouvez pas modifier. C'est peut-être juste une classe ou c'est un arbre d'héritage préexistant. Dans tous les cas, vous souhaitez ajouter une setméthode à une propriété, mais vous ne pouvez pas.
public abstract class A // Pre-existing class; can't modify
{
public abstract int X { get; } // You want a setter, but can't add it.
}
public class B : A // Pre-existing class; can't modify
{
public override int X { get { return 0; } }
}
Problème: ne peut pas overridele get-seulement avec get/set
Vous voulez overrideavec une propriété get/ set, mais elle ne se compilera pas.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Solution: utilisez une abstractcouche intermédiaire
Bien que vous ne puissiez pas directement overrideavec une propriété get/ set, vous pouvez :
Créez une propriété new get/ setavec le même nom.
overridel'ancienne getméthode avec un accesseur à la nouvelle getméthode pour assurer la cohérence.
Donc, vous écrivez d'abord la abstractcouche intermédiaire:
public abstract class C : B
{
// Seal off the old getter. From now on, its only job
// is to alias the new getter in the base classes.
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
Ensuite, vous écrivez la classe qui ne serait pas compilée plus tôt. Il compilera cette fois parce que vous n'êtes pas en fait overridela getpropriété -only; à la place, vous le remplacez à l'aide du newmot - clé.
public class D : C
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } }
// Ensure base classes (A,B,C) use the new get method.
protected sealed override int XGetter { get { return this.X; } }
}
Résultat: tout fonctionne!
De toute évidence, cela fonctionne comme prévu D.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
test.X = 7;
Print(test.X); // Prints "7", as intended.
Tout fonctionne toujours comme prévu lors de la visualisation Dcomme l'une de ses classes de base, par exemple Aou B. Mais, la raison pour laquelle cela fonctionne pourrait être un peu moins évidente.
var test = new D() as B;
//test.X = 7; // This won't compile, because test looks like a B,
// and B still doesn't provide a visible setter.
Cependant, la définition de la classe de base de getest toujours remplacée par la définition de la classe dérivée de get, elle est donc toujours totalement cohérente.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
var baseTest = test as A;
Print(test.X); // Prints "7", as intended.
Discussion
Cette méthode vous permet d'ajouter des setméthodes aux getpropriétés -only. Vous pouvez également l'utiliser pour faire des choses comme:
Changez n'importe quelle propriété en une propriété get-only, set-only ou get-and- set, indépendamment de ce qu'elle était dans une classe de base.
Modifiez le type de retour d'une méthode dans les classes dérivées.
Les principaux inconvénients sont qu'il y a plus de codage à faire et un supplément abstract classdans l'arbre d'héritage. Cela peut être un peu gênant avec les constructeurs qui prennent des paramètres car ceux-ci doivent être copiés / collés dans la couche intermédiaire.