Datentypbewahrung trotz Erbung

mavinatic

Bekanntes Mitglied
Hallo Community,

ich habe ein Problem mit der Gestaltung meines Programms. Ich habe eine Abstrakte Klasse "Value". Davon leiten sich folgende Klassen ab: BinaryValue, BooleanValue, TextValue, ... und so weiter. Nun möchte ich ein Objekt zurückgeben welches eine Ansammlung (Array) verschiedener Datentypen hat.
Jede Klasse hat einen "Key" und ein Value jeweils nach Datentyp - Klassennamen.

Aber wenn ich Value-Array als abstrakten Datentyp zurückgebe, weiß der Benutzer meiner API nicht, welcher DataType am implementiert ist. :-(

Gibts dafür eine gute Lösung?
 

faetzminator

Gesperrter Benutzer
Nunja, du könntest natürlich [c]getType()[/c] oder [c]isBinary()[/c] o.ä. anbieten. Aber da kommts aufs Use Case drauf an. Was hast du damit vor? Wie sollen diese Values verwendet werden?
 

mavinatic

Bekanntes Mitglied
Der Use-Case ist folgender: Ich fordere über eine Schnittstelle ein Objekt an und übergebe der Schnittstelle ein Schema. Nun soll von der Schnittstelle ein Objekt zurückkommen, welches ein Array mit Value-Objekten hat. Je nach Schema wird sind das verschiedene Unterklassen von dem abstrakten Objekt "Value" (BinaryValue, BooleanValue,...).
 
S

SlaterB

Gast
das ist alles ziemlich ungenau,
was weiß der Aufrufer, was will er haben?
ist der Aufruf (quasi-)statisch oder inwiefern spielt noch Konfiguration eines erzeugten Schnittstellen-Objekts eine Rolle?

vereinfacht reden wir vielleicht von einer statischen Methode X.parse(String), die ein Date, einen Integer sowie ein byte[] zurückgeben kann,
diese Methode kann von sich aus offensichtlich nur Object zurückgeben,

denkbar wären:
- Aufrufer caste einfach, weiß ja was er will?

- mehrere unterschiedliche Methoden, X.parseInteger(String) mit Rückgabewert Integer

- Übergabe der Klasse für generisch korrekten Cast:
> public static<T> T parse(String toParse, Class<T> returnClass)

- frei generische Methode, castet auf beliebiges:
> public static<T> T parse(String toParse)

Aufruf:
> Integer k = X.parse("");
kompiliert




ist das das Thema?
Generics bekannt oder zu den letzten beiden Punkten noch Fragen?
die beiden Varianten unterscheiden sich hier weniger als zunächst von mir gedacht,
Class<T> nur für den Cast des Rückgabewert zu übergeben scheint recht sinnlos, hat manchmal noch andere Funktionen,
für Anlegen eines Arrays schon etwas interessanter


wenn es nicht allein um Rückgabewert geht, dann bitte weiter erläutern
 
Zuletzt bearbeitet von einem Moderator:

mavinatic

Bekanntes Mitglied
Ich drücke mich wahrscheinlich ungenau aus :-(

Der Aufrufer fragt ein "Container"-Objekt an...dieses Container-Objekt beinhaltet ein Schema, d.h. verschiedene "Felder" mit Value-Objekten und verschiedenen Datentypen.
Nun soll der Benutzer auf die Value-Objekte zugreifen. Jede Subklasse bietet die Methode addValue(). Jedoch für BinaryValue addValue(byte[] arr) für BooleanValue addValue(Boolean b);
Dieses Container objekt muss nun so designed werden, dass der Benutzer alle ValueObjekte abrufen kann und mit dem jeweiligen Datentyp ausfüllen kann.

D.h. wenn ich meine Klasse
ValueContainer habe kann ich dort kein AbstractValueObject-Array anbieten, denn dadurch weiß der Benutzer nicht, welcher Datentyp verwendet wird für das jeweilige Value-Objekt.

Versteht ihr das vielleicht jetzt?
 

Marco13

Top Contributor
Ein paar Zeilen Pseudocode sagen vielleicht mehr als 363 Worte.
Java:
Value value = container.getValue(someID);
value.addValue(x);
Soll gehen, wobei 'x' dann verschiedene Typen haben kann:
Java:
Value booleanValue = container.getValue(someID);
booleanValue.addValue(someBoolean);

Value intValue = container.getValue(someID);
intValue.addValue(someInt);
Das geht natürlich nur (vernünftig) indem man dort über das Obekt mehr weiß, als dass es nur eine "Value" ist - man MUSS es dort als "BooleanValue" oder "IntValue" kennen:
Java:
BooleanValue booleanValue = container.getValue(someID);
booleanValue.addValue(someBoolean);

IntValue intValue = container.getValue(someID);
intValue.addValue(someInt);

Und das funktioniert wiederumm nur (typsicher), wenn man bei "getValue" schon mit übergibt, welchen Rückgabetyp man erwartet - in der einen oder anderen Form. Z.B.
Java:
BooleanValue booleanValue = container.getValue(someID, BooleanValue.class);
booleanValue.addValue(someBoolean);

IntValue intValue = container.getValue(someID, IntValue.class);
intValue.addValue(someInt);

oder ggf. etwas "distanzierter" und vielleicht allgemeiner:
Java:
interface Value<T>
{
    void setValue(T t);
}

class IntValue implements Value<Integer>
{
    void setValue(Integer t);
}

class Container 
{
    public <T> Value<T> getValue(String id, Class<T> contentType) { ... }
}


Value<Integer> intValue = container.getValue(someID, Integer.class);
intValue.addValue(someInteger);

Aber da ist (wegen der schwammigen beschreibung) noch viel Spekulation drin...
 

mavinatic

Bekanntes Mitglied
Ja...ich finde das schwer zu erklären, weil es alles in meinem Kopf eine Idee zu einem bestehenden Problem ist.

Java:
Container c = myInterfaceObject.requestContainer("MySchema"); //Benutzer fordert einen Container für ein Schema an.
AbstractValue[] values = c.getValues(); // Benutzer ruft alle Felder des Schemas ab. Durch das Array wurde der Datentyp aufgehoben und ich möchte jetzt die abfrage "instanceof" umgehen sowie eine generische Methode
//Durch c.getValues() muss der Benutzer nicht wissen welcher Wert in das ValueObjekt kommt, denn er hat nur die eine Auswahl, welcher Datentyp reinkommt.

Ich hoffe ich konnte das mit dem CodeSnippet verständlich erklären.
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Wie gesagt, dazu muss man an dieser Stelle genauer wissen, welchen Typ man vor sich hat. Zu wissen, dass es AbstractValue ist, reicht nicht, es muss IntValue oder BooleanValue sein. So, wie du es beschrieben hast, HAT die Klasse "AbstractValue" ja gar nicht die Methode "addValue" (sie könnte sie haben, aber auch das wäre auf Basis von AbstractValue dann nicht typsicher)
 
P

Pippl

Gast
Java:
public abstract class AbstractValueItem
{
    protected byte[] value;
    ....
    public abstract void setValue(object o);

    public abstract string getDataType();

    public abstract object getValue();
    ....
}

public class TextValueItem extends AbstractValueItem
{
    public void setValue(object o)
    {
         // hier müssen instance of abfragen rein, natürlich wäre eigentlich fast alles erlaubt da man es als text speichern kann
    }

    public string getDataType()
    {
        return "TEXT";
    }

    public string getValue()
    {
        // wandelt das byte[] in einen string um
    }
}

public class NumberValueItem extends AbstractValueItem
{
    public void setValue(object o)
    {
         // hier müssen instance of abfragen rein, nicht alles kann als nummer/zahl gespeichert werden
         // zwar speichert man es in wirklichkeit als byte[] aber da "text" als number ungültig sein wird/sollt, muss man solche angaben abfangen und entsprechend behandeln
    }

    public string getDataType()
    {
        return "NUMB";
    }

    public int getValue()
    {
        // wandelt das byte[] in ein int oder einen string um (je nachdem wie du es implementieren willst)
    }
}

So kannst du ein AbstractValueItem[] zurückgeben und bei jedem zum Beispiel die setValue Methode aufrufen um einen Wert zu setzen. Natürlich muss eben jede Subklasse von AbstractValueItem die Methode setValue implementieren und intern den Type des Objekts abfragen. Passt es ok, wenn nicht ist es ein Fehler
 
Zuletzt bearbeitet von einem Moderator:

mavinatic

Bekanntes Mitglied
So wäre der Entwurf ja generisch. Kann man das auch machen, das es nicht generisch ist? D.h. setValue(byte[] bytes)?
oder setValue(String s)?
 
P

Pippl

Gast
Naja wirklich generisch ist es ja nicht!

Nein, weil du das Problem hast wenn du nur ein AbstractValueItem[] zurück gibst kannst du ja nur auf Methoden zugreifen die diese Klasse anbietet (natürlich könntest du sie um ... erweitern)
Java:
...
public abstract void setValue(string s);

public abstract void setValue(int i);
...

Aber jeder der Subklassen muss dann jede dieser Methoden implementieren, und auf ein TextValueItem die setValue(int) Methode aufrufen ist wahrscheinlich nicht gewollt!
[EDIT]
In C# gibt es eine Möglichkeit ein Methode als Obsolete zu makieren und wenn die verwendet wird, wird es als Compile Error angezeigt! Weiß nicht ob es sowas für Java auch gibt ...
[/EDIT]

Natürlich kannst du TextValueItem um ... erweitern
Java:
...
public void setValue(string s); // leitet dann intern weiter auf das setValue(object o);
...

Aber hier ist eben das Problem du hast nur ein AbstractItemValue[] zur Verfügung und kannst deshalb diese Methoden nicht aufrufen, oder aber castest es (nach einer Typüberprüfung)
Womit aber das ganze doch wieder etwas unnötig wäre
 
Zuletzt bearbeitet von einem Moderator:

Crian

Top Contributor
Markieren kann man zumindest mit der Annotation @Deprecated. Man kann Eclipse sicher dazu bringen, die Verwendung als Fehler zu ahnden.

Ich glaube, dass hier aber ein intelligenteres Verfahren sinnvoll wäre. Dieses "Schema" sollte in meinen Augen nicht nur ein String sein. Man könnte statt einen schlichten Array zu erzeugen, ein eigenes listenartiges Objekt erzeugen, was anhand des Schemas weiß, an welche Stelle seiner Elemente welche genaue Unterklasse stehen muss und daher beim Abruf dieser auf diese castet. Dann kann man das von außen ganz bequem benutzen.
 
Zuletzt bearbeitet:

Crian

Top Contributor
So ich hab mal was gebastelt dazu. Ob das so die geschickteste Lösung ist, bezweifele ich noch, aber es geht so.

Java:
package forumProblems.values;

public abstract class Value {

    private int key;

    public Value(int key) {
        this.key = key;
    }

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }
}

Java:
package forumProblems.values;

public class IntegerValue extends Value {

    private int value;

    public IntegerValue(int key, int value) {
        super(key);
        this.setValue(value);
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "IntegerValue [value=" + value + ", getKey()=" + getKey() + "]";
    }

}

Java:
package forumProblems.values;

public class BooleanValue extends Value {

    private boolean value;

    public BooleanValue(int key, boolean value) {
        super(key);
        this.value = value;
    }

    public boolean isValue() {
        return value;
    }

    public void setValue(boolean value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "BooleanValue [value=" + value + ", getKey()=" + getKey() + "]";
    }

}

Java:
package forumProblems.values;

import java.util.ArrayList;
import java.util.List;

public class Schema {

    private String identifier;
    private List<Class<? extends Value>> classes;

    @SafeVarargs
    public Schema(String identifier, final Class<? extends Value>... classes) {
        this.setIdentifier(identifier);
        this.classes = new ArrayList<>();
        for (Class<? extends Value> c : classes) {
            this.classes.add(c);
        }
    }

    public String getIdentifier() {
        return identifier;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

    public List<Class<? extends Value>> getClasses() {
        return classes;
    }

    @Override
    public String toString() {
        return "Schema [identifier=" + identifier + ", classes=" + classes
                + "]";
    }

}

Java:
package forumProblems.values;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

public class ValueList {

    private Schema schema;

    private List<Value> values;

    public ValueList(Schema schema) {
        this.setSchema(schema);
        values = new ArrayList<>();
    }

    public Schema getSchema() {
        return schema;
    }

    public void setSchema(Schema schema) {
        this.schema = schema;
    }

    public boolean addNextValue(Value value) {
        if (values.size() < schema.getClasses().size()) {
            if (value.getClass() != schema.getClasses().get(values.size())) {
                throw new InvalidParameterException("An Index " + values.size()
                        + " wurde die Klasse "
                        + schema.getClasses().get(values.size())
                        + " erwartet, geliefert wurde aber die Klasse "
                        + value.getClass() + "!");
            }
            values.add(value);
            return true;
        }
        else {
            return false;
        }
    }

    public void clear() {
        values.clear();
    }

    public Value getValueAt(int index) {
        if (index < values.size()) {
            return values.get(index);
        }
        else {
            throw new InvalidParameterException("values hat nur "
                    + values.size() + " Elemente, angefordert wurde Index "
                    + index + "!");
        }
    }

    public Class<? extends Value> getClassAt(int index) {
        if (index < values.size() && index < schema.getClasses().size()) {
            return schema.getClasses().get(index);
        }
        else {
            throw new InvalidParameterException("classes hat nur "
                    + schema.getClasses().size()
                    + " Elemente, angefordert wurde Index " + index + "!");
        }
    }

    public int size() {
        return values.size();
    }

    public boolean isComplete() {
        return values.size() == schema.getClasses().size();
    }

    @Override
    public String toString() {
        return "ValueList [schema=" + schema + ", values=" + values + "]";
    }

}

Java:
package forumProblems.values;

public class AblaufTest {

    public AblaufTest() {
        ValueList list = generateList();
        System.out.println("Liste: " + list);
        for (int i=0; i<list.size(); ++i) {
            Value value = list.getValueAt(i);
            System.out.println("Value: " + value);
            Class<? extends Value> c = list.getClassAt(i);
            System.out.println("Class: " + c);
        }

    }

    private ValueList generateList() {
        Schema schema = new Schema(
                "b-i-i-b-i",
                BooleanValue.class,
                IntegerValue.class,
                IntegerValue.class,
                BooleanValue.class,
                IntegerValue.class
        );
        ValueList list = new ValueList(schema);
        list.addNextValue(new BooleanValue(10, true));
        list.addNextValue(new IntegerValue(20, 17));
        list.addNextValue(new IntegerValue(21, 59));
        list.addNextValue(new BooleanValue(11, true));
        System.out.println("Liste sollte unkomplett sein: Komplett=" + list.isComplete());
        list.addNextValue(new IntegerValue(22, 92));
        System.out.println("Liste sollte komplett sein: Komplett=" + list.isComplete());
        return list;
    }

    public static void main(String[] args) {
        new AblaufTest();
    }

}

Ausgabe:

Code:
Liste sollte unkomplett sein: Komplett=false
Liste sollte komplett sein: Komplett=true
Liste: ValueList [schema=Schema [identifier=b-i-i-b-i, classes=[class forumProblems.values.BooleanValue, class forumProblems.values.IntegerValue, class forumProblems.values.IntegerValue, class forumProblems.values.BooleanValue, class forumProblems.values.IntegerValue]], values=[BooleanValue [value=true, getKey()=10], IntegerValue [value=17, getKey()=20], IntegerValue [value=59, getKey()=21], BooleanValue [value=true, getKey()=11], IntegerValue [value=92, getKey()=22]]]
Value: BooleanValue [value=true, getKey()=10]
Class: class forumProblems.values.BooleanValue
Value: IntegerValue [value=17, getKey()=20]
Class: class forumProblems.values.IntegerValue
Value: IntegerValue [value=59, getKey()=21]
Class: class forumProblems.values.IntegerValue
Value: BooleanValue [value=true, getKey()=11]
Class: class forumProblems.values.BooleanValue
Value: IntegerValue [value=92, getKey()=22]
Class: class forumProblems.values.IntegerValue
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W Null-Pointer trotz Konstruktor? Java Basics - Anfänger-Themen 9
heinrich172 Methoden Trotz gleichem Element stimmt Vergleich nicht? Java Basics - Anfänger-Themen 7
U Breite von Textfeldern trotz Layoutmanager Java Basics - Anfänger-Themen 4
I Programm erkennt nicht an das Array zurückgegeben wird trotz Initialisierung *einfach* Java Basics - Anfänger-Themen 9
tun3d Packet trotz richtiger Addressierung nicht auffindbar? Java Basics - Anfänger-Themen 10
P Apache Derby wird in Eclipse trotz Anbindung nicht gefunden Java Basics - Anfänger-Themen 6
Kotelettklopfer Output korrekt trotz falschem Lösungsweg !? Java Basics - Anfänger-Themen 99
P NoClassDefFoundError: org/apache/commons/collections4/ListValuedMap trotz vorhandener Klasse? Java Basics - Anfänger-Themen 10
E Timer trotz erwartender Eingabe durchlaufen lassen Java Basics - Anfänger-Themen 11
V_Fynn03 Erste Schritte JButton funktioniert nicht trotz richtiger Methode. Java Basics - Anfänger-Themen 17
J bundel - Datei wird nicht gefunden. Trotz STRG-SHIFT-J Java Basics - Anfänger-Themen 2
U UnsupportedClassVersionError trotz neuster JRE und JDK Version Java Basics - Anfänger-Themen 7
J Unterschiedliche Ordnerstrukturen trotz gleicher Entwicklungsumgebungen Java Basics - Anfänger-Themen 3
M java.io.FileNotFoundException trotz dass Verzeichnis korrekt angegeben ist! Java Basics - Anfänger-Themen 20
helldunkel While Schleife trotz false Java Basics - Anfänger-Themen 4
L Methoden if Bedingung trotz Erfüllung, nicht angesprochen Java Basics - Anfänger-Themen 12
L [Verständnisproblem] Array wird trotz void rückgabe verändert. Java Basics - Anfänger-Themen 5
C Threads SwingWorker läuft trotz cancel weiter Java Basics - Anfänger-Themen 22
M Interpreter-Fehler Nullpointerexception trotz Ordentlicher Initialisierung Java Basics - Anfänger-Themen 4
D javac kann trotz PATH-Eintrag nicht gefunden werden (Hello World) Java Basics - Anfänger-Themen 10
P Threads Trotz Threads wird nur 1 Prozessorkern ausgelastet Java Basics - Anfänger-Themen 7
A Heap Space Error bei rekursiver Suche in Dateien trotz nur einer Zeile im Speicher Java Basics - Anfänger-Themen 26
X Array trotz Befüllung "null" Java Basics - Anfänger-Themen 11
M Arrayfelder werden trotz Beschränkung unbeschrenkt ausgegeben Java Basics - Anfänger-Themen 2
Fab1 alte Java Datei wird ausgeführt (trotz Änderung) Java Basics - Anfänger-Themen 4
O Downloaden: Trotz If Abfrage wird Datei heruntergeladen Java Basics - Anfänger-Themen 2
L Applet : keine Recht für Zugriff auf Clipboard (trotz Zertifikat) Java Basics - Anfänger-Themen 4
N Input/Output EOF-Exception trotz Fehlerüberprüfung Java Basics - Anfänger-Themen 2
U Übersicht trotz mehrdimensionaler Arraylisten Java Basics - Anfänger-Themen 17
S Java Heap space trotz -Xmx1024 Java Basics - Anfänger-Themen 10
J trotz Error weitermachen Java Basics - Anfänger-Themen 4
V Kein neuer Thread trotz Runnable Java Basics - Anfänger-Themen 4
X JFrame als JAR unsichtbar trotz Exception Handling Java Basics - Anfänger-Themen 5
Y Trotz add wird Image in GradBagLayout nicht angezeigt Java Basics - Anfänger-Themen 5
L Polymorphie <identifier> expected trotz "Angabe" Java Basics - Anfänger-Themen 2
O ausgabe spinnt trotz erfolgreichem kompilieren Java Basics - Anfänger-Themen 2
D Jar klappt nicht trotz main Methode Java Basics - Anfänger-Themen 19
S JButton trotz Box-Layout skalieren Java Basics - Anfänger-Themen 6
D OpenCSV Fehllender Konstruktor trotz import und Buildpath Eintrag Java Basics - Anfänger-Themen 1
X dll löschen trotz zugriff durch java programm Java Basics - Anfänger-Themen 5
U if-Anweisung trotz Division/0 Java Basics - Anfänger-Themen 6
K BufferedReader/Writer trotz Cache? Java Basics - Anfänger-Themen 9
D Ein boolean[] Array größer als 63.000.000 erstellen? trotz -Xms und -Xmx.... Java Basics - Anfänger-Themen 7
Q Listen - DefaultListModel trotz Design ueber GUI? Java Basics - Anfänger-Themen 10
A Trotz Thread ist Program nicht erreichbar Java Basics - Anfänger-Themen 3
Q Vector verändert trotz final seine Größe Java Basics - Anfänger-Themen 5
A kein zugriff auf variable trotz public? Java Basics - Anfänger-Themen 3
D nicht genug speicher - profiling trotz error Java Basics - Anfänger-Themen 5
D Buttons gehen trotz enebled(false) Java Basics - Anfänger-Themen 8
J Spielfigur wird trotz erfolgreich aufgerufener Methode nicht Java Basics - Anfänger-Themen 22
H javac Befehl trotz Variablen einbindung ned gefunden Java Basics - Anfänger-Themen 23
C Trotz "synchronized" unerwartete Ausgabe Java Basics - Anfänger-Themen 2
K Midi stoppt trotz stop button nicht Java Basics - Anfänger-Themen 3
R windowclosing - fenster schließt immer trotz abfrage Java Basics - Anfänger-Themen 2
C Thread läuft und läuft, trotz interrupt() Java Basics - Anfänger-Themen 9
T laagen trotz Double-Buffering Java Basics - Anfänger-Themen 5
S ClassNotFoundException trotz JAR Einbindung in Eclipse Java Basics - Anfänger-Themen 2
T tooltip trotz gedrückter maustaste Java Basics - Anfänger-Themen 2
0 NoSuchMethodError: main trotz vorhandener Main Methode? Java Basics - Anfänger-Themen 9
Silver-Blue mehrere Instanzen einer Klasse, trotz Random immer das Selbe Java Basics - Anfänger-Themen 7
X trotz gleicher variablen nicht equal Java Basics - Anfänger-Themen 5
G Trotz Abfrage immer noch Zahlen doppelt Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben