J'écris deux classes en C #:
Matrix
représentant une matrice générale avec des dimensions N-BY-MSquareMatrix
qui hérite de Matrix
et a la contrainte d'être N-by-NLa raison pour laquelle je l'ai conçue de cette façon est que des matrices carrées prennent en charge des opérations spécifiques supplémentaires telles que le calcul du déterminant ou de l'inverse, de sorte de garanifier que ces fonctions sont disponibles avec le type spécifique que vous utilisez sont de belles choses à utiliser. En outre, il prendrait en charge toutes les opérations matricielles ordinaires et peut être utilisée comme matrice
J'ai une fonction dans Matrix
appelé getTranspose()
. Il calcule la transposition de la matrice et le renvoie comme un nouveau Matrix
Je hérite de le hériter dans SquareMatrix
, mais parce que la transposition d'une matrice carrée est garantie pour être une matrice carrée, je veux aussi qu'il retourne un SquareMatrix
Je ne suis pas sûr de la meilleure façon de le faire.
SquareMatrix
, mais ce serait une duplication de code parce que c'est essentiellement le même calculSquareMatrix
à Matrix
, créez une nouvelle Matrix
comme transposez, créez une nouvelle SquareMatrix
lors de la typée et jetez les tranches Matrix
)SquareMatrix
explicitement, et il a également le même problème de l'opérateur implicite avec des allocations inutilesY a-t-il une autre option? Devrais-je changer la conception d'avoir SquareMatrix
hériter de Matrix
?
Ce problème s'applique également aux opérateurs. Il semble que je dois soit implémenter des opérateurs de caractères de texte qui pourraient coûter en performance, ou avoir à ré-implémenter le même code.
Le problème est que le concept de "ce type" manque au C #. Il peut être simulé mais il utilise une syntaxe un peu complexe ou déroutant, et je ne conseillerais pas l'utiliser. La question ci-dessous décrit une telle mise en œuvre.
https://stackoverflow.com/questions/1400831/is-it-possible-à-Make-Ce-type-for-généric-in-c
Utilisez l'opérateur "Nouveau" dans la fonction héritée pour remplacer la sortie et appeler la classe de base à l'aide de l'opérateur "Base".
Quelque chose comme:
public new SquareMatrix getTranspose()
{
// Do something different here... or not...
return (SquareMatrix)base.getTranspose();
}
La pénalité de performance pour la coulée que vous suggérez n'est pas réelle, rien n'est réaffecté si vous lancez un type de base à un type dérivé. Vous pouvez donc le faire en toute sécurité sur les destinataires. Si le code client sait qu'il obtiendra un type plus riche, car il a créé la classe dérivée, elle peut lancer le type retourné au type plus riche, de préférence en utilisant l'opérateur "comme". Ce n'est pas du tout mal pratique.
Si vous êtes vraiment bugié par le Cast In Code client, vous pouvez ajouter une méthode supplémentaire dans la classe dérivée (avec un nom légèrement différent). Vous n'avez pas besoin de réimplémenter quoi que ce soit comme vous le suggérez, vous appelleriez la base.getTransposez et faites la distribution avant le retour.
Les génériques n'entraîneraient pas beaucoup ici car le type T devrait être la classe mise en œuvre plutôt que sur un type de variante qui y est manipulé. C'est impossible.
La suggestion d'Alan est un piratage, il tuerait la virtualité de la méthode de descendants.
Mais voici le kicker: votre idée d'utiliser une classe dérivée pour mettre en œuvre une contrainte est fausse. Il viole le LSP et est la cause première de votre problème même. Vous devriez simplement avoir une propriété Issquare à la place de votre classe de base.