Cast, héritage et surcharge ...

LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009 - 31 mai 2006 à 01:12
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 - 31 mai 2006 à 14:50
Bonsoir à tous ...

Alors voilà ... J'ai une classe Matrix qui possède - entre autre - les
propriétés Height et Width, qui correspondent respectivement à la
hauteur et à la largeur d'une matrice. J'ai aussi une classe Vector qui
hérite de la classe Matrix, sachant qu'en fait un vecteur n'est qu'une
simple matrice dont la propriété Height vaut 1.

Du coup, je me suis mis en tête de coder deux opérateurs de cast pour
passer de Matrix à Vector si cela est possible, et de Vector à Matrix,
sachant que cela est également toujours possible. Mais là, le
compilateur me sort que ce n'est pas utile .

Alors que dois-je faire ? Y a-t-il une solution autre que de créer des méthodes statiques telles que ToVector ou ToMatrix ?

Mais ce n'est pas terminé  ! ...
Dans la classe Matrix, j'ai surchargé l'opérateur arthmétique +. Ainsi,
si A et B sont 2 matrices, alors A + B retourne une matrice. Mais le
problème, c'est que si A et B sont 2 vecteurs, alors A + B va retourner
une matrice et non un vecteur, sauf si je recommence à surcharger cet
opérateur dans la classe Vector. Or j'aimerais éviter ça, puisque c'est
justement pour ça que j'ai voulu que Vector hérite de Matrix. Alors
est-il possible d'effectuer une sorte de cast automatique ou quelque
chose comme ça ?

Merci de vos réponses !
LocalStone

23 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
31 mai 2006 à 01:33
Salut comme ça rapidement, juste pour la première question je dirais qu'une Matrix dérive d'un Vector.. plus on descend dans l'héritage plus les objets sont évolués..
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 07:29
Bah oui, mais en même temps pas vraiment ... La classe Vector possède toutes les propriétés de Matrix (ce qui logique puisqu'on peut parfaitement calculer la transposée d'un vecteur colonne, par exemple), mais aussi d'autres méthodes, telles que le calcul de la norme, etc. Donc dans un sens, Vector est plus évolué que Matrix  ...
LocalStone
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
31 mai 2006 à 08:37
Salut,
A vrai dire, un Vector hérite d'une Matrice plutôt que l'inverse
Par contre, si tu surcharge l'opérator d'addition, je ne vois pas d'autre solution que d'en mettre un par classe. Car : 

1 matrice + 1 matrice = 1 matrice et
1 vecteur + 1 vecteur = 1 vecteur (ou 1 matrice... puisqu'un vecteur est une matrice).

Donc soit tu utilises la méthode mère (de Matrice) qui te retournera une matrice (que tu peux éventuellement ensuite convertir en vecteur) soit tu implémentes une surcharge de l'opérator d'addition dans le vecteur. Tu peux aussi faire des casts implicits et explicits comme l'illustre cet exemple

<hr size="2" /> VC# forever
=13319
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 10:48
Merci pour ta réponse Bidou.
J'ai déjà essayer de faire des casts explicit ou implicit pour passer d'une classe à l'autre. Mais le compilateur refuse de les utiliser parce qu'il dit que c'est inutile. En fait, l'exception vient du fait que l'une des classe soit dérivée de l'autre ... Du coup ... Bah ça marche pas.
Localstone
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 10:52
C'est normal que le compilateur te jette :

Si ton vecteur dérive de matrice, alors ton vecteut EST une matrice... donc pas besoin de caster en matrice, tu utilise directement les fonction de la classe matrice depuis ton vecteur.
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 10:55
Et concernant l'addition... le plus simple et le plus logique est surchargé aussi dans Vecteur l'opérateur d'addition, puis il a un comportement particulier (il renvoie un vecteur)
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
31 mai 2006 à 10:59
Exacte, ça n'a pas de sens de les caster, puisqu'ils sont déjà du même type.
Pour utiliser les fonctions de la class Matrice depuis ton Vecteur, tu utilises le mot clef base.

<hr size= "2" /> VC# forever
=13319
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 11:01
Ok. Là, je comprends  !
Mais dans ce cas, est-ce qu'il serait possible de faire ... Bah j'en sais pas trop comment ... Quelque chose qui convertisse directement une matrice de hauteur n et de largeur 1 en vecteur ?
Je m'explique ... Si je fais :

Matrix m;
m = new Matrix(3, 2);// Création d'une matrice de hauteur 3 et de largeur 2 ...
Console.WriteLine(m.Norm()); 

Cela n'a pas de sens puisque la classe Matrix n'a pas de telle méthode ...

Par contre, si je fais :

m = new Matrix(3, 1);
Console.WriteLine(m.Norm());

Bah là, ça à un sens puisque m est un vecteur ... Si il y a ce "cast automatique" !
Voilà voilà ... Dans l'espoir de ne pas avoir été trop bordélique dans mes explications ...
LocalStone
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 11:09
Bidou > pas besoin de base pour accéder aux fonctions de la classe mère (sauf si tu les a surchargés dans la classe fille), tu y accède directement.

LocalStone > Pour caster explicitement et avoir accès à la méthode Norm de Vector :

Matrix m;
m = new Matrix(3, 1);
Console.WriteLine( ( (Vector)m ).Norm());

Par contre, attention, comme tu le dis, il faut que ta fonction Norm (qui pourrait être une propriétés, en passant) soit prévues pour géré les cas d'erreur, c'est a dire lorsque elle recoit une "vrai matrice" avec au moins 2 dimensions... Dans ce cas, soit tu renvoie une erreur, soit tu calcul uniquement sur la premiere colonne...

Ce que je te conseillerai c'est par exemple de rajouter une méthode static dans Vector qui teste si une matrice est un vecteur. Puis :

m = new Matrix(3, 2);
if(Vector.IsVector(m))
{
    ...
}
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
31 mai 2006 à 11:14
Oui je sais, c'est une convention que j'ai prise et que je trouve très bien. Pour chaque variable de classe, j'utilise base ou this. C'est beaucoup plus clair je trouve (et ça fait plus orienté object, on voit clairement à ce qu'on accède)

<hr size= "2" /> VC# forever
=13319
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 11:19
Heu encore mieux en fait :

Défini toi même le cast d'un Vecteur depuis une Matrix :

public static explicit operator Vector(Matrix m)
{
// tu ne garde que la premiere colonne
return new Matrix(m.X, 1);
}

Ce qui sera appelé lorsque tu fera :

Vector v = (Vector)m;
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 11:26
Bidou > C'est beaucoup plus clair je trouve (et ça fait plus orienté object, on voit clairement à ce qu'on accède) >>

Mouai, personnellement j'aurai dit tout l'inverse ;) (les appels aux méthodes héritées/surchargée ou non doit être transparent et implicite) comme quoi...
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
31 mai 2006 à 11:38
Ma fois... chacun sa convention... héhé.

<hr size= "2" /> VC# forever
=13319
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 12:52
En fait, je crois avoir trouvé un moyen assez élégant de résoudre mon problème, mais je ne sais pas trop comment le mettre en oeuvre ... Il suffit en fait de faire un test dans le constructeur.
Suposons que le constructeur soit écrit de la manière suivante :

public Matrix(int height, int width)
{
    if (height == 1)
    {
       // Alors on a un vecteur ...
       ?// On instancie non pas un type Matrix, mais un type Vector.
    }
    else
    {
       // On a une matrice normale, et donc on continue à instancier normalement...
       ...
    }
}

Ainsi, si on fait :

Matrix m;
m = new Matrix(5, 1); // m ne sera non pas une matrice mais un vecteur ... Et le monde est beau !

Mais le truc, c'est que je ne sais absolument pas comment faire ça. Au niveau de la programmation orientée objet, ça reste cohérent, je trouve ... Enfin bon ... Si quelqu'un à une idée ...Merci !
LocalStone
P.S. : Moi aussi, j'utilise tout le temps les base et les this ... C'est plus ... Euh ... Structuré.
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 13:05
Tu ne peux pas renvoyer autre chose qu'une matrix dans le constructeur de matrix....

Il n'y a pas de solution mirable, si tu déclare cela :

m = new Matrix(5,1);

alors tu déclare forcément une matrice.. (d'ailleur tu peux vouloir déclarer une matrice a une dimension, sans pour autant avoir besoin qu'elle est toutes les fonctionnalités d'un vecteur)

si tu veux déclarere explicitement un vecteur, tu dois faire :

v = new Vector(5);

Dans quel cas as tu besoin de déclarer une matrice qui est en fait un vecteur?
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 13:06
Ha oui ! Je dis que c'est élégant parce que si une telle implémentation est possible, je n'ai aps besoin de redefinir toutes opérations entre matrices et vecteurs ... Exemple :
J'ai  une matrice a et un vecteur b, et la classe matrice gère le produit de 2 matrices. La fonction qui calcule ce produit est obligé à un moment ou à un autre de créer une nouvelle matrice. Et il se trouve que le produit de a  et b donne une matrice de largeur 1, donc cette matrice issue du produit va "se transformer" toute seule (comme une grande) en vecteur. Et c'est magique !
LocalStone
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 13:07
Bah y a eu du crosspost, mais j'ai lu dans tes pensées parce que ça répond à ta question !
Localstone
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 13:17
Je vois ce que tu veux dire, mais dans le morceau de code ou tu vas faire ton produit de matrices, tu va récupérer parfois une matrice a n dimensions, parfois une matrice a une dimension. Dans ce cas tu aimerai récupérer non pas une matrice mais un vecteur... mais quelle utilité ? puisque dans ton code effectuant le produit, tu ne sais pas ce que tu peux récupérer tu es obligé de traiter le cas "général". Et si tu dois faire un tratement particulier dans le cas ou il s'agit d'un vecteur, tu aura forcément un test sur le résultat, et un traitement particulier associé (dans ce cas : tu peux tester la dimension de ta matrice résultat et si elle est unique, tu cast en (Vector) et tu fais ton traitement...)

Bref, je ne sais pas si je suis très clair, mais :
- Un produit de matrice donne une matrice.
- Une matrice peut etre un vecteur

-> tu dois pouvoir tester si une matrice est un vecteur (en testant ses dimensions par exemple)
-> tu dois pouvoir caster une matrice en vecteur (en utilisant le code en haut de cette page)

Je ne vois pas trop dans quel cas ca te poserai problème qu'un produit de matrice donne forcément une matrice (cette matrice pouvant être de dimension unique, et pouvant donc être considérée comme un vecteur...). Et même si il a quand même dans ton code un cas ou tu dois absolument utiliser un vecteur et non une matrice si la dimension est de 1, alors tu as tout ce qu'il faut pour tester et caster...
0
Nikoui Messages postés 794 Date d'inscription vendredi 24 septembre 2004 Statut Membre Dernière intervention 19 août 2008 13
31 mai 2006 à 13:35
Et concernant un produit de vecteur, si tu as définis le produit de matrice, tu n'a pas a redéfinir le produit de vecteur. Mais juste a écrire :

v = (Vector)(v1 * v2); // Utilise le produit de matrice, renvoie une matrice que tu cast car tu sais qu'il s'agit d'un vecteur
0
LocalStone Messages postés 514 Date d'inscription mercredi 19 mars 2003 Statut Membre Dernière intervention 1 mars 2009
31 mai 2006 à 14:07
Grrr ...  
J'ai choisi de faire comme tu as dit ... En utilisant les casts et en abandonnant cette idée de transformation automatique ...
Mais du coup, le code pour caster une Matrix en Vector ne fonctionne pas, puisque l'on cast un type de base vers un type dérivé (et si on défini l'opérateur de cast dans Vector, alors on cast un type dérivé vers un type de base, et ça marche pô non plus ...) ... Et on retombe sur le même problème ...  Dois-je choisir la corde pour résoudre ce problème  ?
Plus serieusement, je suppose que je ne suis pas le seul avoir été confronté à ça, donc il doit forcement exister une solution quelque part ...
LocalStone
0
Rejoignez-nous