Erweiterung der String-Klasse

  • Themenstarter Themenstarter Anfängerin
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
A

Anfängerin

Gast
Hallo,

ich muss fürs Studium ne Erweiterung der String-Klasse schaffen, ohne diese abzuleiten. Da das ja auf Grund des Schlüsselwortes final nicht geht. Nun habe ich ein Programm von nem Kommilitonen in die Finger bekommen. Checke aber einfach nicht, was der da mit dem Konstruktor macht. Bzw. was der da überhaupt macht. Kann mir das vielleicht jemand in "einfacher Anfänger-Sprache" erklären? Gibt es eventuell auch noch einen anderen Weg die String-Klasse zu erweitern? Ich wäre euch allen sehr dankbar für baldige Antworten 🙂

Code:
public class StringExt {

	// Ein String als Attribut
	private String str;
	
	/**
	 * Konstruktor für unser StringExt Objekt
	 *
	 * @param str  Der String
	 */
	public StringExt(String str) {
		// Das Attribut stetzen
		this.str = str;
	}
	

	/**
	 * Wandelt unser StringExt Objekt wieder in ein String Objekt um, 
                 * so dass es ganz normal benutzt werden kann
	 */
	public String toString() {
		return str;
	}
	
	
	/**
	 * Ein Beispiel für eine Methode:
	 * Dem String werden drei Punkte angehängt.
	 */
	public void addDots() {
		str = str + "...";
	}
}


public class Testbed {

	/**
	 * Die Main Methode, die beim Programmstart
	 * ausgerufen wird.
	 *
	 * @param args  Wird nicht benutzt
	 */
	public static void main(String[] args) {
		// So wird die neue StringExt Klasse
		// benutzt:
		
		// Ein neues StringExt Objekt mit dem
		// Inhalt "blablabla" erstellen...
		StringExt testString = new StringExt("blablabla");
		
		// ...am Ende drei Punkte anhängen...
		testString.addDots();
		
		// ...und auf dem Bildschirm ausgeben
		System.out.println(testString);
	}
}
 
Also die genaue Aufgabenstellung war:

Die Klasse String wurde im JDK als final deklariert und kann daher nicht abgeleitet werden. Das schränkt ihre Anwendbarkeit und insbesondere ihre Erweiterbarkeit stark ein. Überlegen Sie sich, auf welche Weise ohne Ableitung neue String-Methoden entwickelt werden können und zeigen Sie deren Vor- und Nachteile auf.

Falls ich mich mit Erweiterung missverständlich ausgedrückt habe..
 
Was verstehst du daran nicht?

Der übergibt dem Konstruktor nen String, dieser wird deiner str Variable zugewiesen....ganz normal eigentlich.

Dieser String soll dann wohl den "erweiterten" String repräsentieren, auf den die Methoden deiner neuen Klasse angewandt werden.
 
Eine Möglichkeit in Java ist die Aggregation. Das hat auch dein Kommilitone gemacht. Dabei schreibst du eine neue Klasse, die eine Referenz zu einem String-Objekt hält. Oftmals hört man auch den Ausdruck "Wrapper" oder "Wrapper-Klasse".

Eine andere Möglichkeit ist eine "Werkzeug"-Klasse mit statischen Funktionen, denen du als Parameter ein String-Object übergibst:
Code:
public final class StringUtil {
  public static String addDots(String s) {
    return s.concat("...");
  }
}

public class Testbed {
  public static void main(String[] args) {
     String testString = StringUtil.addDots("blablabla");
  }
}
 
mic checker:

na dass das "ganz normal" ist, was mein Kommilitone macht, habe ich ja nie bezweifelt. Deshalb habe ich mich ja auch Anfängerin genannt und diese Frage in das Anfänger-Forum gestellt. Weil ich mich eben noch nicht so auskenne mit Java. Ich sehe, dass er dem Konstruktor eine String Variable übergibt und dieser dann den Wert der anderen Variablen zuweist. Ich verstehe nur nicht den Sinn der dahinter steckt, bzw. was das mit der Lösung der Aufgabenstellung zu tun hat...

Gast:

Vielen Dank, jetzt bin ich aber echt erstaunt. So wie das Programm, was du geschrieben hast, hatte ich es auch gemacht. Dann war ich mir nicht mehr sicher, ob es wirklich eine so einfache Antwort auf die Frage ist. Oder ob ich irgendwas nicht bedacht habe. Nachdem ich dann das andere Programm von meinem Kollegen gesehen hatte (und da nicht durchgestiegen bin), dachte ich meine Möglichkeit ist falsch - weil da ja eigentlich wirklich nichts dabei war, die Methode so zu erweitern... Naja, die Sache mit dem anderen Programm hab ich nur leider immer noch nicht kapiert. Aber trotzdem vielen Dank
 
mic checker Nachtrag:

sorry, ich meinte: ... und dann den Wert des Übergabeparameters der private Variablen str zuweist nicht umbekehrt.
 
soo, der dritte Beitrag hintereinander, aber ich glaub jetzt hab ichs grad kapiert. Also wenn ich im Konstruktor schreibe: this.str = str, dann gilt diese Zuweisung für die ganze Zeit, während mit dem Objekt von StringExt gearbeitet wird...!? Das heißt, wenn bei addDots() die Variable str verändert wird, ändern sich automatisch beide Variablen, oder wie?

wäre sehr dankbar, wenn nochmal jemand sagen könnte, ob das jetzt stimmt.. :roll:
 
Ja und nein. Normal sind es halt zwei Referenzen zum selben Objekt und es wird deshalb verändert, egal welche Referenz man benutzt. String ist aber ein Sonderfall. Die Zeichenkette von einem String-Objekt lässt sich nicht verändern und es muss immer ein neuer String erstellt werden. Danach zeigen die Referenzen nicht mehr zum selben Objekt. Verständlich?
 
Ums mal anders auszudrücken als der zweite Gast: Vom Prinzip stimmt was du gesagt hast, nur dass es bei String noch die kleine Besonderheit gibt, die er gesagt hat. Also: Wenn addDots aufgerufen wird, bekommt str das neue String-objekt zugewiesen. Wenn nun toString aufgerufen wird, gibt testString danach eben auch das neue str - Objekt zurück.
 
hmmm ???:L

aber toString() wird doch in den beiden Klassen überhaupt nicht aufgerufen und trotzdem hat sich der Wert des StringExt Objektes auch verändert...

Sorry, schlagt mich, kratzt mich, beißt mich.. aber irgendwie hat es wohl immer noch nicht klick gemacht. --> Ich bitte dies zu entschuldigen, würde mich sehr über einen (oder mehrere) weitere Erklärungsversuche freuen, will aber auch sicher niemanden damit nerven
 
Anfängerin hat gesagt.:
aber toString() wird doch in den beiden Klassen überhaupt nicht aufgerufen und trotzdem hat sich der Wert des StringExt Objektes auch verändert...

toString() ist eine Methode, die implizit aufgerufen werden kann, wenn aus einem beliebigen Objekt ein String gemacht werden soll. Im Quelltext deines Kommilitonen wird toString() z. B. innerhalb von System.out.println() aufgerufen.

Anfängerin hat gesagt.:
Sorry, schlagt mich, kratzt mich, beißt mich.. aber irgendwie hat es wohl immer noch nicht klick gemacht. Ich bitte dies zu entschuldigen, würde mich sehr über einen (oder mehrere) weitere Erklärungsversuche freuen, will aber auch sicher niemanden damit nerven

Was genau verstehst du denn nicht? Was dort passiert? Oder etwa warum man sowas macht? Bitte etwas konkreter.
 
ok, also ich versuche nochmal ganz genau zu beschreiben wo mein Problem liegt:

Der Konstruktor ist ja nichts anderes als eine Methode. Und eine Methode ist ja nur so lange aktiv, wie sie ausgeführt wird. Das bedeutet: Anfangs wird der Konstruktor aufgerufen und ein Objekt der Klasse StringExt erstellt mit dem String Wert "blablabla". Und dieser wird dann durch den Konstruktor der Variablen private String str zugewiesen. Gut, aber diese Zuweisung ist ja nun geschehen. Und ich verstehe irgendwie nicht richtig, warum dann nach dem Aufruf der Methode addDots() plötzlich auch der Wert des StringExt Objektes mit geändert wird. Wo doch in der Methode addDots() nur die Rede von dem private String str ist. Ist das nun wirklich eine spezielle Eigenschaft des Konstruktors, dass sich dann beide verändern? Oder liegt das eigentlich an etwas anderem, was ich die ganze Zeit übersehe?
 
1. Konstruktor != Methode. Ein Konstruktor hat bspw. keinen Rückgabewert.

2. Schau dir mal die Methode addDots an:

Code:
      str = str + "...";

Der neue String wird erzeugt, da Strings unveränderlich sind, doch die Referenz von deinem str zeigt auf diesen neu erzeugten String.
 
Anfängerin hat gesagt.:
Und ich verstehe irgendwie nicht richtig, warum dann nach dem Aufruf der Methode addDots() plötzlich auch der Wert des StringExt Objektes mit geändert wird. Wo doch in der Methode addDots() nur die Rede von dem private String str ist.
"this.str" ist eine private Eigenschaft der Instanz (und keine Variable in einer Methode/Konstruktor). Die Eigenschaft behält so lange ihren Wert, wie die Instanz der Klasse referenziert wird (und nicht geändert wird natürlich). Das heißt folglich: Wenn man in einer Methode/Konstruktor eine Eigenschaft der Instanz ändert, so kann man auf den Wert in einer anderen Methode zugreifen. Hoffe das war jetzt verständlich?
 
Ist es so mit dem Konstruktor einfacher zu verstehen?

Code:
public class StringExt {

   // Ein String als Attribut
   private String str;
   
   /**
    * Konstruktor für unser StringExt Objekt
    *
    * @param str  Der String
    */
   public StringExt(String aString) {
      // Das Attribut stetzen
      str = aString;
   }
   

   /**
    * Wandelt unser StringExt Objekt wieder in ein String Objekt um,
                 * so dass es ganz normal benutzt werden kann
    */
   public String toString() {
      return str;
   }
   
   
   /**
    * Ein Beispiel für eine Methode:
    * Dem String werden drei Punkte angehängt.
    */
   public void addDots() {
      str = str + "...";
   }
}


public class Testbed {

   /**
    * Die Main Methode, die beim Programmstart
    * ausgerufen wird.
    *
    * @param args  Wird nicht benutzt
    */
   public static void main(String[] args) {
      // So wird die neue StringExt Klasse
      // benutzt:
      
      // Ein neues StringExt Objekt mit dem
      // Inhalt "blablabla" erstellen...
      StringExt testString = new StringExt("blablabla");
      
      // ...am Ende drei Punkte anhängen...
      testString.addDots();
      
      // ...und auf dem Bildschirm ausgeben
      System.out.println(testString);
   }
}
 
Vielen Dank für die eure ganzen lieben Erklärungsversuche..

ICH HABS NU ENDLICH KAPIERT!!!!

Hab nun auch begriffen, dass mein eigentliches Problem diese doofe toString() Methode war. Also.. Ums nochmal abzuschließen: Wenn ich mit sop(Teststring) den Wert des StringExt Objektes ausgeben will, wird IMPLIZIT toString() aufgerufen, da ja ein String ausgegeben werden soll. Und toString() hat ja keine andere Aufgabe, als die str Variable aus StringExt zurückzugegeben. Das heißt also es wird ja letztendlich gar nicht der Wert des StringExt Objektes ausgegeben, sondern einfach nur der Wert der anderen str Variablen!!!

Sorry Illuvator, ich habe gesehen, so ziemlich das hast du mir versucht zu erklären... :roll:


So, und nun sagt bitte niemand, dass da jetzt noch irgendwas falsch dran war
 
Anfängerin hat gesagt.:
Hab nun auch begriffen, dass mein eigentliches Problem diese doofe toString() Methode war. Also.. Ums nochmal abzuschließen: Wenn ich mit sop(Teststring) den Wert des StringExt Objektes ausgeben will, wird IMPLIZIT toString() aufgerufen, da ja ein String ausgegeben werden soll. Und toString() hat ja keine andere Aufgabe, als die str Variable aus StringExt zurückzugegeben. Das heißt also es wird ja letztendlich gar nicht der Wert des StringExt Objektes ausgegeben, sondern einfach nur der Wert der anderen str Variablen!!!

System.out ist vom Typ java.io.PrintWriter und dessen Methode println() ist mehrfach überladen. Es gibt z.B. System.out.println(Object obj) und so kann man jedes Objekt rausschreiben. Da aber println() nicht weiß, wie ein Objekt als String aussieht, muß jedes Objekt sich selbst darum kümmern. Jede Klasse sollte deshalb die Methode toString() überschreiben, damit z.B. System.out.println(Object o) einfach nur noch String s = o.toString() aufrufen muß. Genaugenommen wird toString() also nicht implizit aufgerufen, sondern natürlich explizit in println(Object). War 'ne Notlüge. :bae:
 
Achso, achso, achso.. ob mans glaubt oder nicht, aber da wird ja noch alles richtig schlüssig 😀

Hätt ich ja nicht mehr für möglich gehalten.

Das einzige Wort, welches ich jetzt an deinem Text - lieber Ur-Gast - nicht kapiert habe, war das Wort "überladen". Was heißt es denn, wenn eine Methode überladen ist?
 
Anonymous hat gesagt.:
Das einzige Wort, welches ich jetzt an deinem Text - lieber Ur-Gast - nicht kapiert habe, war das Wort "überladen". Was heißt es denn, wenn eine Methode überladen ist?

das heisst, dass es in einer klasse mehrere methoden mit gleichem namen aber unterschiedlichen parametertypen gibt. in PrintWriter gibt es z.b. die methoden print(int) und print(String). beide heissen gleich, erwarten aber einen anderen parameter -> überladen
 
Anonymous hat gesagt.:
Ja und nein. Normal sind es halt zwei Referenzen zum selben Objekt und es wird deshalb verändert, egal welche Referenz man benutzt. String ist aber ein Sonderfall. Die Zeichenkette von einem String-Objekt lässt sich nicht verändern und es muss immer ein neuer String erstellt werden. Danach zeigen die Referenzen nicht mehr zum selben Objekt. Verständlich?


So das Check ich jetzt nicht ganz.
So wie ich das immer verstanden habe wird doch nur eine neue Instanz des Objekets erzeugt die dann aber mit dem
Ursprünglichen Objekt nichts mehr zu tun hat.
Also referenziert sie auch nicht mehr darauf.... ???

Z.B.



Sagen wir mal es gäbe die Methode HansWurst() in der Klasse Object


public void HansWurst(Object o)
{


//Macht irgendwas..... z.B.

o = new Vector();

}



public Static void main(String[] paras)
{

Object1 = new Object();
Object2 = new Object();

Object1.HansWurst(Object2);


}


So in Object2 ist meiner Meinung nach der Dynamische Typ aber trotzdem kein Vector, da ich nur mit dem Parameter eine Instanz erzeugt habe, die dann dynamisch in einen Vector gecastetet wird.
Ich bin mir sogar ziemlich sicher.


Fazit es wird über den Parameter eine Instanz erzeugt und keine Referenz vom Object.

Oder täusche ich mich da?



mfg GagamehlO
 
GagamehlO hat gesagt.:
So in Object2 ist meiner Meinung nach der Dynamische Typ aber trotzdem kein Vector, da ich nur mit dem Parameter eine Instanz erzeugt habe, die dann dynamisch in einen Vector gecastetet wird.
Ich bin mir sogar ziemlich sicher.
Ja, du darfst dir sogar vollkommen sicher sein. Aber inwiefern widerspricht das dem, was ich (als Gast oder Ur-Gast) gesagt habe? Es ging um die Methode addDots() und daß dort ein neues String-Objekt erzeugt wird und deshalb nicht mehr das gleiche Objekt ist, das man auch dem Konstruktor übergeben hat. Übrigens ist Instanz keine korrekte Übersetzung vom englischen "instance".
 
Ok alles klar.

Jedoch ist eine Instanz eigentlich etwas was seiner Vorgabe entspricht.
Also denke ich mal das man auch hier Instanz sagen könnte.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben