2012-04-07 11 views
1

Ich habe folgendes Modell:Casting Unter-Entitäten zwischen einander

abstract Article {id, name, text} 

final NewspaperArticle { printDate } extends Article 

final ScientificArticle { quotations, publicationDate } extends Article 

final ... { ... } extends Article 

Ich frage mich, wie ich erreichen konnte die letzten Einheiten untereinander werfen, so dass die gemeinsamen Felder von Artikel geordneten Klasse festgelegt werden würde und die verschiedenen Felder würde null bleiben. Etwas wie:

Ist es möglich, es zu werfen, oder ich muss Reflexion verwenden?

+3

Design-weise ist das Gießen zwischen NewspaperArticle und ScientificArticle nicht gültig nach Liskows Substitutionsprinzip (http://en.wikipedia.org/wiki/Liskov_substitution_principle). Ein NewspaperArticle ist eine bestimmte Art von Artikel und könnte daher einen ersetzen. Sie können jedoch dasselbe für die endgültigen Entitäten nicht beanspruchen. –

+0

Ich stimme zu, es ist vielleicht nicht "korrekt", aber ich muss es irgendwie erreichen. –

+0

Ich habe herausgefunden, dass es ziemlich gut ist, oft an Kompositionen zu denken (sie repräsentieren gemeinsame Teile vieler Klassen durch eine eigene Klasse, von denen sie ein Objekt erhalten), in seltenen Fällen von Vererbung (wenn Sie Vererbung vorzeitig anwenden, können Sie ernst werden Probleme später, wie ich in einer Firma gesehen habe) und nie der Reflexion (Sie brauchen keine Reflexion für die normale Programmierung, nur für "Meta-Programmierung"). –

Antwort

1

Um Ihre Frage kurz zu beantworten: Nein, Sie können ein Objekt nicht in eine andere Klasse umwandeln. Sie können nur in Supertypen der realen Klasse des Objekts umwandeln. (A-Klasse ist auch ein übergeordneter Typ von selbst.)

konnte Sie verwenden jedoch Zusammensetzung statt Vererbung:

interface Article { ArticleData getArticleData(); } 

final ArticleData {id, name, text} 

final NewspaperArticle { articleData, printDate } implements Article 

final ScientificArticle { articleData, quotations, publicationDate } implements Article 

final ... { articleData, ... } implements Article 

Dann Sie einen Konstruktor wie NewspaperArticle(Article createFrom) jeder Klasse hinzufügen könnte, die die Artikeldatenfeld setzt und lässt die anderen null:

class NewspaperArticle { 
    ArticleData articleData; 
    Date printDate = null; 

    NewspaperArticle(Article createFrom) { 
    this.articleData = createFrom.getArticleData(); 
    } 
} 

Ihr Beispiel würde dann wie folgt aussehen:

ScientificArticle scientificArticle = ...; 
NewspaperArticle newspaperArticle = new NewspaperArticle(scientificArticle); 
+0

Ich wollte es nicht so machen, denn sobald sich die Article-Schnittstelle in Zukunft ändert - zum Beispiel wird eine Spalte hinzugefügt - kann die Änderung im Konstruktor vergessen werden und das Feld wird nicht kopiert. Ich wollte es irgendwie "automatisch" machen. –

+1

@ Vojtěch Das Feld konnte nicht vergessen werden, wie ich es implementiert habe. Bitte sehen Sie es sich noch einmal an: Der einzige Ort, an dem ein Feld hinzugefügt werden muss, ist die ArticleData-Klasse. Innerhalb des Konstruktors wird das ArticleData-Objekt verwendet. ArticleData muss jedoch unveränderlich sein, damit dies funktioniert. Ein anderer Ansatz wäre, Cloneable zu machen (siehe [Object.clone()] (http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#clone())). –

+0

Ok, mein Schade, tut mir leid. Es ist eine Möglichkeit, aber es bricht das aktuelle Design meiner persistenten Entitäten: / –

2

Sie können das nicht tun, denn NewspaperArticle enthält einige Informationen (z. B. Felder), die ScientificArictle nicht hat. Ich weiß auch nicht, wie Sie das durch Reflexion erreichen wollen. Und selbst wenn Sie könnten, wäre das ein Zeichen für schlechtes Klassen-Design, wenn Sie sich auf solche Dinge verlassen müssen.

+0

"Foreach Getter, wenn es einen Setter gibt, benutze ihn." - Warum sollte es schlechtes Design sein? So kann ich sicher sein, dass ich nie vergessen werde, die Entity aus der Klasse der "copyOf" -Methode hinzuzufügen. –