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 new
propriété qui a à la fois un get
et un en set
utilisant le même nom.
Si vous ne faites rien d'autre, l'ancienne get
mé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 abstract
couche intermédiaire qui utilise override
l'ancienne get
méthode pour la forcer à renvoyer le get
résultat de la nouvelle méthode.
Cela nous permet de remplacer les propriétés par get
/ set
mê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: get
proprié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 set
mé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 override
le get
-seulement avec get
/set
Vous voulez override
avec 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 abstract
couche intermédiaire
Bien que vous ne puissiez pas directement override
avec une propriété get
/ set
, vous pouvez :
Créez une propriété new
get
/ set
avec le même nom.
override
l'ancienne get
méthode avec un accesseur à la nouvelle get
méthode pour assurer la cohérence.
Donc, vous écrivez d'abord la abstract
couche 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 override
la get
propriété -only; à la place, vous le remplacez à l'aide du new
mot - 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 D
comme l'une de ses classes de base, par exemple A
ou 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 get
est 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 set
méthodes aux get
proprié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 class
dans 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.