Avendo una funzione ereditata restituisce il tipo derivato al posto del tipo base

4

Sto scrivendo due classi in C #:

  • Una classe Matrix che rappresenta una matrice generale con dimensioni n-by-m
  • Una classe SquareMatrix che eredita da Matrix e ha il vincolo di essere n-by-n

Il motivo per cui l'ho progettato in questo modo è perché le matrici quadrate supportano operazioni specifiche aggiuntive come il calcolo del determinante o dell'inverso, quindi essere in grado di garantire che tali funzioni siano disponibili con il tipo specifico che si sta utilizzando sono cose carine da avere. Inoltre, supporta tutte le normali operazioni Matrix e può essere usato come una matrice

Ho una funzione in Matrix chiamata getTranspose() . Calcola la trasposizione di Matrix e la restituisce come una nuova Matrix

L'ho ereditato in SquareMatrix , ma siccome la trasposizione di una matrice quadrata è garantita come matrice quadrata, voglio anche che restituisca un SquareMatrix

Non sono sicuro del modo migliore per farlo.

  • Posso ri-implementare la funzione in SquareMatrix , ma quella sarebbe la duplicazione del codice perché è essenzialmente lo stesso calcolo
  • Posso utilizzare gli operatori di typecast impliciti, ma se ho capito correttamente ciò causerebbe allocazioni non necessarie (upcast SquareMatrix a Matrix , crea un nuovo Matrix come trasposizione, crea un nuovo SquareMatrix durante typecasting e throw via il transposed Matrix )
  • Posso usare espliciti operatori typecast, ma sarebbe stupido dover tipografare esplicitamente la trasposizione di SquareMatrix , e ha anche lo stesso problema dell'operatore implicito con allocazioni non necessarie

C'è un'altra opzione? Dovrei cambiare il design di avere SquareMatrix ereditare da Matrix ?

Questo problema si applica anche agli operatori. Sembra che sia necessario implementare operatori di typecasting che potrebbero costare in termini di prestazioni o dover implementare nuovamente lo stesso codice.

    
posta 9a3eedi 27.08.2014 - 04:03
fonte

2 risposte

5

L'ereditarietà che non aiuta a eliminare la ripetizione e le tipizzazioni è spesso un segno che i farmaci generici potrebbero aiutare. Puoi fare qualcosa come:

public T getTranspose<T>()
// or non-member function
T getTranspose<T>(T input)

Non l'ho ancora risolto, ma sembra che potrebbe essere complicato dal lato delle chiamate. So che C # fa qualche deduzione con metodi generici, ma non conosco C #, quindi non ho familiarità con i dettagli. Questo potrebbe essere il modo in cui devi andare, però, se vuoi eseguire il controllo completo del tipo in fase di compilazione con la minor quantità di ripetizioni nell'implementazione.

Un'altra opzione sarebbe quella di creare funzioni di supporto private, quindi passare il tipo di risultato desiderato, affinché l'helper possa compilare, come:

public SquareMatrix getTranspose() {
    SquareMatrix result = new SquareMatrix();
    transposeHelper(result);
    return result;
}

Questo ti dà più informazioni sul lato dell'implementazione, ma almeno non è una ripetizione completa.

Una terza opzione è solo per verificare se il risultato è quadrato nell'implementazione Matrix e restituire un SquareMatrix se lo è, ad esempio:

public Matrix getTranspose() {
   Matrix result; 
   if (resultIsSquare())
        result = new SquareMatrix();
   else
        result = new Matrix();

   // calculate result
   return result;
}

Questo ha il vantaggio di non aver bisogno di alcuna implementazione per getTranspose() in SquareMatrix , ma a spese di richiedere il controllo del tipo del valore di ritorno nel sito di chiamata. Funziona anche per casi come moltiplicare due matrici non quadrate che danno luogo a un risultato quadrato. Tuttavia, si rinuncia alla maggior parte del controllo del tipo in fase di compilazione.

Se per caso la tua applicazione richiede principalmente il run-time invece del controllo del tipo in fase di compilazione, potresti anche rinunciare ai diversi tipi e lanciare un'eccezione se chiami un metodo che una matrice non quadrata non supporto. Credo che questo sia l'approccio adottato dalla maggior parte delle librerie, soprattutto perché ci sono altre condizioni oltre a non essere quadrati che possono causare il fallimento di metodi come inverse() .

Parlando di biblioteche, ci sono molti buoni là fuori per matematica matematica, che sono già pesantemente testati e ottimizzati. Non reinventare la ruota se non è necessario.

    
risposta data 27.08.2014 - 05:39
fonte
1

Il problema è che il concetto di "questo tipo" manca in C #. Può essere simulato ma utilizza una sintassi un po 'complessa o confusa e non consiglierei di usarlo. La domanda seguente descrive una tale implementazione.

link

    
risposta data 27.08.2014 - 08:49
fonte

Leggi altre domande sui tag