Java Format von eingenem Datentyp bei Konstruktoraufruf

PoiZz3n

Cadet 2nd Year
Registriert
Sep. 2014
Beiträge
20
Liebes Forum,

ich habe die folgende offene Datentypklasse:

Code:
public class Datum
{
    public int tag;
    public String monat;
    public int jahr;
      
}


und eine Oberklasse:

Code:
public abstract class Sportler
{
    
    protected String name;
    protected Datum geburtsdatum;
    
   
    
    public Sportler(String name, Datum geburtsdatum)
    {
        
        
        
        this.name = name;
        this.geburtsdatum = geburtsdatum;
        
        
    }
    
    
    public void istTeammitglied()
    {
    }
    
    public String toString()
    {
    
        String res = this.name + " " + this.geburtsdatum;
        
        return res;
    }
   
}

sowie eine Unterklasse:

Code:
public class Fussballspieler extends Sportler
{
    public Fussballspieler(String name, Datum geburtsdatum)
    {
                               
        super(name, geburtsdatum);
        
    }
    
    
}

Nun möchte ich eine Instanz der Klasse Fussballspieler erzeugen, jedoch ist mir nicht klar in welchem Format ich einen Wert des Datentypes Datum meinem geerbten Konstruktor übergeben kann. Falls bereits ein Datum (Objekt) per explizitem Konstruktor erzeugt wurde, funktioniert das ganze, da ich einfach das Objekt als Parameter übergeben kann. Es ist gefordert, dass kein expliziter Konstruktor für das Datum definiert werden soll.

Ich habe zunächst folgendes versucht:

Code:
public static void main(String[] args)
    {

    Fussballspieler test = new Fussballspieler("Thomas Mueller", 24, "August", 1990);
       
    }

was mit folgender Meldung abgelehnt wird:

constructor Fussballspieler in class Fussballspieler cannot be applied to given types;
required : java.lang.String,Datum
found: java.lang.String, int, java.lang.String, int
reason: actual and formal argument lists differ in length

Die Meldung besagt doch prinzipiell, dass der Typ der Argumente nicht passt? Es wird anstatt ein Datum ein int, String und noch ein int übergeben. Meine Frage ist nun, wie ich ein Argument des Types Datum angeben kann, ohne ein Objekt per (explizitem) Konstruktor zu erzeugen bzw. ob das überhaupt möglich ist?

Liebe Grüße
 
Naja... du übergibst dem Fussballspieler-Konstruktor ja quasi einen String, dann nen int, wieder nen String und nochmal nen int.
Laut Definition erwartet dieser aber einen String für den Namen und bereits ein "fertiges"/erzeugtes Datums-Objekt.

Was heißt in dem Kontext "expliziter" Konstruktor?
Du sollst keinen Eigenen schreiben?
Dann arbeitest du mit dem Standard-Konstruktor Datum(), den jede Klasse zur Verfügung stellt, solange kein anderer Konstruktor geschrieben wurde.

Dein Problem an der Stelle wäre aber, dass du niemals einen Wert in die Variablen des Datum-Objekts eintragen kannst.
 
Zuletzt bearbeitet:
du willst ein objekt vom typ datum übergeben ohne eines zu erzeugen? das ist arg schwer oder? was genau du da machen willst ist mir nicht ganz klar aber könntest du dein problem nicht damit lösen indem du gleich eine arraylist erzeugst und einen konstruktor aufrufst der dein objekt mit allen attributen anlegt? nur mal so meine frage :)
 
"geburtsdatum" ist vom Typ Datum. Dein Aufruf ist also falsch.

Du musst aufrufen
new Fussballspieler("Thomas Mueller", new Datum(???));

Ich würde nicht den Typ "Datum" empfehlen - den müsstest nämlich noch bauen. Nimm lieber LocalDate: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html

Das erzeugen ist sehr leicht:

new Fussbalspieler("peter", LocalDate.of(2000, Month.JANUARY, 1));

da muss man kein Programmierer sein um das lesen zu können
 
Zuletzt bearbeitet:
dermoritz schrieb:
"geburtsdatum" ist vom Typ Datum. Dein Aufruf ist also falsch.

Du musst aufrufen
new Fussballspieler("Thomas Mueller", new Datum(???));

ja aber er will ja kein datumobjekt erzeugen :) deshalb sollte er lieber gleich in der superklasse attribute fürs datum deklarieren da alle erbenden klasse auch ein geburtsdatum aufweisen dürften :)
 
Ist nicht (sinnvoll) möglich. Ändere die Signatur oder biete einen weiteren Konstruktor an, der die Einzelteile eines Datums erwartet. Alternativ kannst du dir das Builder-Pattern ansehen.

Es scheint mir aber nicht sinnvoll das hier aufzubrechen und das aus mehreren Gründen:
  • ein Konstruktor mit 4 Parametern ist für meinen Geschmack schon grenzwertig
    • da Java keine named parameters hat, sieht man den Argumenten nicht an, wo nun Tag, Monat oder Jahr hingehört
  • eine Validierung der Eingaben bläht den Konstruktor von Fussballspieler/Sportler auf, statt da zu sein wo es hingehört - im Konstruktor des Datums.
    • zugegeben, du könntest die Einzelteile im Konstruktor des Sportlers immer noch in ein Datums-Objekt verpacken, was wiederum validiert, aber dieses Durchschleifen bläht alle Signaturen auf dem Weg auf

Sollte das hier nicht von der Aufgabe vorgegeben sein, solltest du bereits existierende Datums-/Kalenderklassen von Java nutzen und nicht das Rad neu erfinden mit allerlei Schwächen. Das fängt schon mit Vertippern beim Monat an, weil du keine Konstanten (enum) anbietest. Deutsche Monatsnamen werden den französischen Kollegen zudem sehr unglücklich machen, wenn er deinen Code für seine Zwecke nutzen will. Von Schaltjahren und der Frage, welcher Monat nun 30 oder 31 Tage haben darf, mal ganz abgesehen. :)
 
Zuletzt bearbeitet:
[...]als Erstes eine offene Datentypklasse Datum, die sich aus Feldern für den Tag (Ganzzahl),
den Monat und das Jahr zusammensetzt. Warum brauchen Sie in dieser Klasse keinen
Konstruktor? Geben Sie die Antwort im Quelltext der Klasse.[...]

[...]Der Name und das Geburtsdatum werden durch Weitergabe geeigneter
Parameterwerte an den super-Konstruktor gesetzt (Gebrauch von Wiederverwen-
dung).[...]

Mir ist schon klar, dass das ganze nicht wirklich Sinn ergibt, es soll lediglich der Umgang mit Konstruktoren und Vererbung etc. eingeübt werden. Ich wüsste jedoch nicht, wie ich die Aufgabenstellung anders übersetzen sollte, als meine Variante, die ja offensichtlich nicht funktioniert. :confused_alt:
 
sie funktioniert. Tausche nur "Datum" gegen "LocalDate" aus. Wenn du auf deiner Datum-Klasse bestehst (würde dringend davon abraten) gib ihr einfach einen Konstruktor. Und mach am besten alle Felder private.
 
Zuletzt bearbeitet:
Die Aufgabenstellung erwartet wohl, dass du new Datum() aufrufst, die Referenz einer Variable zuweist und dann auf diesem erstellten Objekt die öffentlichen Felder setzt. Danach kannst du die Referenz an den Konstruktor des Fussballspielers übergeben.
 
TPZ schrieb:
Naja... du übergibst dem Fussballspieler-Konstruktor ja quasi einen String, dann nen int, wieder nen String und nochmal nen int.
Laut Definition erwartet dieser aber einen String für den Namen und bereits ein "fertiges"/erzeugtes Datums-Objekt.

Was heißt in dem Kontext "expliziter" Konstruktor?
Du sollst keinen Eigenen schreiben?
Dann arbeitest du mit dem Standard-Konstruktor Datum(), den jede Klasse zur Verfügung stellt, solange kein anderer Konstruktor geschrieben wurde.

Dein Problem an der Stelle wäre aber, dass du niemals einen Wert in die Variablen des Datum-Objekts eintragen kannst.

Genau das ist gemeint, ich darf keinen eigenen Konstruktor für das Datum schreiben.


Tumbleweed schrieb:
Die Aufgabenstellung erwartet wohl, dass du new Datum() aufrufst, die Referenz einer Variable zuweist und dann auf diesem erstellten Objekt die öffentlichen Felder setzt. Danach kannst du die Referenz an den Konstruktor des Fussballspielers übergeben.

Das Problem ist hierbei jedoch, dass das Geburtsdatum im Konstruktor ausgegeben werden MUSS:

[Implementieren Sie] eine abstrakte Klasse Sportler. Eine Sportler besitzt die folgenden für Subtypen
sichtbare individuelle Eigenschaften: einen Namen und ein Geburtsdatum. Diese Eigenschaften
werden im Konstruktor gesetzt. [...]
 
Code:
Datum datum = new Datum();
datum.tag = 24;
datum.monat = "August";
datum.jahr = 1990;
Fussballspieler spieler = new Fussballspieler("Thomas Müller", datum);
Nicht getestet/kompiliert, aber so ist das gemeint.
 
sorry hab ich erst jetzt gelesen: du brauchst keinen Konstruktor weil die Felder public sind (das ist nebenbei bemerkt sehr schlechte Praxis). du kannst einfach machen:

Datum gebDatum = new Datum();
gebDatum.tag = 1;
gebDatum.monat = "Januar";
gebDatum.jahr = 1920;

new Fussballspieler("Klaus", gebDatum);
 
Zuletzt bearbeitet:
Hmm jaa, das sollte funktionieren.

Vielen Dank an alle für die schnelle Hilfe! :)
 
Zuletzt bearbeitet:
Was ist denn jetzt davon vorgegeben und was nicht? *kopfkratz*

Der Sportler ist, so wie er da steht, nicht abstract. Eventuell sollte istTeamMitglied() abstract sein?

Und: soll jetzt die Signatur für den Fußballspieler so aussehen wie sie dasteht oder hast Du das selbst für Dich so gemacht?

Ohne jetzt zu wissen, was "ist" und was "soll" wird es schwierig.


Ansonsten würd ich vorsichtig sagen, daß Du im OP schon den (grundsätzlich) richtigen Ansatz hattest mit
Code:
    Fussballspieler test = new Fussballspieler("Thomas Mueller", 24, 8, 1990);
, auch wenn man das natürlich wie bereits erwähnt einschränken sollte auf gültige Parameter.

Es fehlt nur der passende Konstruktor dazu für den Fußballspieler, an dieser Stelle also
Code:
    public Fussballspieler(String name, int geburtstag, int geburtsmonat, int geburtsjahr) {}
oder Vergleichbarem.

Die restliche Logik käme dann in diesen Konstruktor: ob der Tag gültig ist, ob der Monat gültig ist, ob das Jahr wie ein Jahr aussieht, ob alles zusammen ein gültiges Datum ausmacht. Dann das für Sportler erforderliche [Datum] instanzieren und mit den übergebenen Werten befüllen, Name dazu und fertig ist die Instanz des Fußballspielers (per super() ).

Hey presto, an keiner Stelle muß nun ein Konstruktor für Datum aufgerufen werden (da macht Fussballspieler(name,tag,monat,jahr) für mich).

Wobei ich persönlich der Ansicht bin, daß man sich eine Instanzierbarkeit von Objekten mit möglicherweise undefinierbaren Zuständen gar nicht erst angewöhnen sollte. Was soll denn ein Datum sein, wo Jahr und Tag gesetzt sind und Monat aber NULL? Ein Datumsobjekt könnte einen internen Schlüssel wie zB einen UNIX-Timestamp verwenden, sodaß new Datum(timestamp) dieses Datum ergibt, oder man könnte public Datum() im Konstruktor mit einem definierten Zustand belegen (zB "heute").

Bitte nicht so nen komischen Fuz angewöhnen, wo man ein "halbes" oder "dreiviertel" Datum bekommen kann.
 
Wir implementieren ein Grundgerüst für die Verwaltung von Sportmannschaften. Implementieren
Sie dafür
(a) als Erstes eine offene Datentypklasse Datum, die sich aus Feldern für den Tag (Ganzzahl),
den Monat und das Jahr zusammensetzt. Warum brauchen Sie in dieser Klasse keinen
Konstruktor? Geben Sie die Antwort im Quelltext der Klasse.
(b) eine abstrakte Klasse Sportler. Eine Sportler besitzt die folgenden für Subtypen
sichtbare individuelle Eigenschaften: einen Namen und ein Geburtsdatum. Diese Eigenschaften
werden im Konstruktor gesetzt. Außerdem ist in der Klasse eine abstrakte
Objektmethode istTeammitglied(...) defniert.
Redefinieren Sie die toString()-Methode (implizit geerbt von java.lang.Object). Sie
soll den Namen und den Geburtstag ohne die Jahreszahl zurückgeben.
(c) eine konkrete Klasse FussballSpieler, die von Sportler erbt. Sie speichert für jeden
Spieler in einem für Subtypen sichtbarem Objektfeld, ob er sich gerade in einer
Mannschaft bendet. Dieses Feld wird im Konstruktor mit false initialisiert und soll
über eine setzte-Methode veränderbar und über die Methode istTeammitglied(...)
abfragbar sein. Der Name und das Geburtsdatum werden durchWeitergabe geeigneter
Parameterwerte an den super-Konstruktor gesetzt (Gebrauch von Wiederverwen-
dung).
Außerdem gibt es eine Methode istTorwart(...). Ein Spieler ist zunächst kein Torwart.

Das ist der Teil der Aufgabe, der direkt mit meinem Problem zu tun hat, der Rest hat jetzt nicht mehr direkt was hiermit zu tun.

Die Signatur hatte ich nur testweise angefügt, um (wenn auch nicht erfolgreich) zu verdeutlich, wo genau mein Problem liegt. Die korrekte Lösung muss nicht so aussehen.

Warum ist der Sportler nicht abstrakt ? Ich dachte, dass das durch das Schlüsselwort abstract bei der Definition geschieht? BlueJ versieht das Klassenkästchen auch mit "abstract". Dein Ansatz für den Konstruktor beim Fussballer macht schon Sinn, nur meine ich laut Aufgabe den Konstruktor von Sportler erben zu müssen. :confused_alt:
 
Zuletzt bearbeitet:
[...]als Erstes eine offene Datentypklasse Datum, die sich aus Feldern für den Tag (Ganzzahl),
den Monat und das Jahr zusammensetzt. Warum brauchen Sie in dieser Klasse keinen
Konstruktor? Geben Sie die Antwort im Quelltext der Klasse.[...]
Einen public Konstruktor braucht man aber immer (sofern man keine statische Klasse nachbilden möchte), sonst kann man Objekte nicht instantiieren.:D Ist in diesem Fall natürlich der default Konstruktor gemeint.
 
Zuletzt bearbeitet:
Dachte mir schon sowas mit istTeamitglied() :)

Einfach deklarieren: public abstract bool istTeamMitglied() (void ist für isIRGENDWAS() eher unsinnig). Nicht vergessen, daß konkret DIESE Methode mit genau DIESER angegebenen Signatur (hier: keine Argumente) in Fussballspieler() implementiert werden muß.

Welche Methode wie zu bauen ist steht ja da. Und toString() nicht vergessen.


Eine abstrakte Klasse definiert sich darüber, daß sie nicht vollständig implementiert ist. Dadurch kann sie nicht instantiiert werden.

Genaugenommen ist nicht die Klasse selber abstrakt, sondern es gibt (mindestens einen) abstrakten Eintrag in ihr - Property, Methode, XXX), ergo man kommt an diesen Eintrag nicht ran, ergo die Klasse ist unvollständig, ergo man muß - notwendigerweise! -- dieses abstrakte Feld irgendwo anders bauen und bei OO heißt das "in einer abgeleiteten Klasse".

Deswegen bekommt auch die Klasse den abstract-Modifikator. Das sagt JAVA, daß ein new Klasse() nicht geht und nicht gehen kann und daß man nur von ihr ableiten kann.

Hier im Beispiel haben wir ja nun Sportler (als allgemeine Klasse) und Fußballspieler (als spezifische Klasse). Beide können potentiell Teammitglieder sein, aber was ein Teammitglied ausmacht, kann man für Sportler nicht festlegen. Das geht nur für die einzelnen "Arten" (Unterklassen) der Sportler.

Also definiert der Sportler eine Standard-Schnittstelle in Form von istTeamMitglied() und sagt aber gleichzeitig, die eigentliche Implementierung, sprich wie man bestimmen soll, OB der einzelne (abgeleitete) Sportler ein Teammitglied ist oder nicht, müssen die anderen machen --- müssen aber dazu den bereitgestellten Namen verwenden (istTeamMitglied()) und nicht irgendwas anderes.

Analog könnte eine Klasse Fahrzeug die Methoden Losfahren() und Beschleunigen() definieren, aber da E-Autos und Hybrid-Autos und Benziner und Diesel und sogar Pferdekutschen ANDERE Dinge machen müssen, UM loszufahren (oder zu beschleunigen) kann die Fahrzeugklasse das nur abstrakt vorgeben und muß die Perdekutschen zum Beschleunigen "Hü" sagen lassen und die Benziner aufs Gaspedal treten lassen.
 
Zuletzt bearbeitet von einem Moderator:
G00fY schrieb:
Einen public Konstruktor braucht man aber immer (sofern man keine statische Klasse nachbilden möchte), sonst kann man Objekte nicht instantiieren.:D
Ich bin mir nicht sicher, was du mit "statische Klasse nachbilden" meinst, aber sonst - nö. :D

Um das hier nicht ins offtopic zu treiben mach ich es kurz - Stichworte hier wären static factory method (am bekanntesten vermutlich durch singletons) und builder pattern (reflection lassen wir mal weg). Gute Lektüre dazu ist u.a. Effective Java von Joshua Bloch.
 
Zurück
Oben