PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java: Immer noch keine echten Templates?


Gast
2004-03-12, 17:23:47
Es ist erstaunlich, dass überhaupt jemand dieses Spielzeug nutzt. Aber meine Erfahrung zeigt mir, dass Werkzeuge oft dann besonders verbreitet sind, wenn sie nicht so "schwer" sind. C++ ist zwar viel ausgereifter, viel
performanter und bietet tausendmal mehr Möglichkeiten (Template-Metaprogramming) als Java, trotzdem findet Java vor allem bei den nicht ganz so begabten "Entwicklern" eine weite Verbreitung, da man sich dann trotzdem wie ein "richtiger" Programmiere fühlen kann, obwohl man gar nicht zu wirklich richtiger Programmierung in Lage ist.

Meisten sind Java-"Programmierer" die gleichen Leute, welche sich auch "Web-Programmierer" schimpfen, weil sie mal mit Frontpage ne HTML-Seite erstellt haben.

Nagilum
2004-03-12, 18:01:11
*Gähn*

Das Trollen lernen wir aber noch wenn wir gross sind, oder?

ethrandil
2004-03-12, 18:19:28
... und ich dachte schon es geht um VB ...

Menschmensch @ Threadstarter du erwartest hier keine ernsthafte Diskussion, oder?

- Eth

Gast
2004-03-12, 19:58:26
@4 Lehrzeichen: ;D

Gast
2004-03-12, 20:03:52
Außerdem:
Warum gibt es eigentlich kein 'const' in Java? Das macht doch eigentlich das OO-Konzept kaputt.
Angenommen ich habe ein privates Objekt in einer Klasse. Wenn ich das mit einer Get-Methode zurück gebe, dann gebe ich doch die Referenz zurück. Die Referenz kann ich aber nach belieben manipulieren. Also kann ich die Member-Variable, die das Objekt hält, gleich als public deklarieren.
Als einzige Möglichkeit, dass zu umgehen, fällt mir nur ein clone() ein. Aber die Geschwindigkeit von Programmen leidet dann natürlich ganz beträchtlich.
Das zweite Problem sind doch die Methodenparameter. Wie kann ich sicher sein, dass eine Methode die Objekte, die ich übergebe, nicht verändert? clone() entfällt aus Geschwindigkeitsgründen und ein Kommentar reicht mir nicht

ethrandil
2004-03-12, 20:18:13
Original geschrieben von Gast
Außerdem:
Warum gibt es eigentlich kein 'const' in Java? Das macht doch eigentlich das OO-Konzept kaputt.
Angenommen ich habe ein privates Objekt in einer Klasse. Wenn ich das mit einer Get-Methode zurück gebe, dann gebe ich doch die Referenz zurück. Die Referenz kann ich aber nach belieben manipulieren. Also kann ich die Member-Variable, die das Objekt hält, gleich als public deklarieren.
...
Das zweite Problem sind doch die Methodenparameter. Wie kann ich sicher sein, dass eine Methode die Objekte, die ich übergebe, nicht verändert?...

Mir fallen gleich mehrere Vorschläge ein.
Trotzdem hätte ich gerne ein konkreteres Beispiel. So weiß ich nichtmal wofür du sowas brauchst.

Danke

- Eth

ethrandil
2004-03-12, 20:35:00
So, hier eine Möglichkeit:

Wenn du möchtest, dass eine andere Klasse die Objekte, die zurückgegeben werden nicht verändern kann, dann machst du das so:

Du definiert ein Interface, das keine Veränderungen zu lässt:

public interface ImmutableObject {
public int getValue();
}


Dies ist das was andere Klassen sehen dürfen.
Deine andere Klasse definiert nun eine 'Inner-class', die das Interface nutzt. Und der Rückgabetyp deiner Methode ist dann halt das Interface:

public class ConstFinally {
private ConstObject co = new ConstObject();

public void action(){
co.setValue(5); //Das wird sich nicht mehr ändern!
}

public ImmutableObject gibConstObject(){
return co;
}

private class ConstObject implements ImmutableObject{
private int value;

public int getValue() {
return value;
}

protected void setValue(int i) {
value = i;
}
}
}


Ich halte das für eine sehr saubere Lösung!

Du könntest einwerfen, dass das nicht für Klassen wie 'Button' funktioniert. Das stimmt. Aber welche Klasse braucht schon deinen ganzen Button? da reicht dann z.b. eine Funktion "public String getButtonText()". String ist unveränderlich.

- Eth

EDIT: Das funktioniert ja auch für Methodenaufrufe. gibst das Interface an.

grakaman
2004-03-12, 21:34:39
Das löst aber nicht das Problem, was der Gast anspricht. Außerdem wird in deinem Bsp. sowieso eine Kopie des int zurückgeliefert, da es sich hierbei um einen Wertetyp handelt. Ich weiß nicht, wie das bei Java ist, aber bei .NET wird beim Manipulieren eines Strings _immer_ ein neues Objekt erstellt. Es kann also gar nicht erst der Fall eintreten, dass man den Rückgabewert (bei einem String) verändert. Bei Java wird das ja hoffentlich genau so sein, ansonsten wäre hier die Get Methode tatsächlich sinnlos.
MfG

ethrandil
2004-03-12, 21:43:17
Original geschrieben von grakaman
Das löst aber nicht das Problem, was der Gast anspricht.Außerdem wird in deinem Bsp. sowieso eine Kopie des int zurückgeliefert, da es sich hierbei um einen Wertetyp handelt.
Dochdoch, du schaust auf die falsche Methode :)

public ImmutableObject gibConstObject(){
return co;
}

Das dort zurückgegebene Objekt erfüllt die Bedingung des Gastes:
1.) Es wird ein Objekt zurückgegeben. (Kein Wertetyp!)
2.) Innerhalb des Eltern-Objektes ist es veränderbar ( public void action() ).
3.) Außerhalb des Eltern-Objektes ist es nicht veränderbar, denn es wird nur das Interface zurückgegeben, welches keinen setter hat.
4.) Kein einziges clone().

Zum String: Ja, beim String ist es genauso wie du es beschrieben hast. Deswegen hat man beim Zurückgeben von Strings keine Probleme.

- Eth

grakaman
2004-03-12, 21:49:59
Original geschrieben von ethrandil
Dochdoch, du schaust auf die falsche Methode :)



Das dort zurückgegebene Objekt erfüllt die Bedingung des Gastes:
1.) Es wird ein Objekt zurückgegeben. (Kein Wertetyp!)
2.) Innerhalb des Eltern-Objektes ist es veränderbar ( public void action() ).
3.) Außerhalb des Eltern-Objektes ist es nicht veränderbar, denn es wird nur das Interface zurückgegeben, welches keinen setter hat.
4.) Kein einziges clone().


Aber es geht hier um die GetValue Methode, die den Wert zurückliefert. Und ein int ist wohl in Java auch ein Wertetyp. Interfaces bieten hier auch keinen richtigen Schutz, denn niemand könnte einen daran hindern das Objekt zu casten, das muss schon der Zugriffsmodifizierer machen.

ethrandil
2004-03-12, 22:03:33
Original geschrieben von grakaman
Aber es geht hier um die GetValue Methode, die den Wert zurückliefert. Und ein int ist wohl in Java auch ein Wertetyp.
Ja, okay. Im Endeffekt muss irgendwann immer ein Wertetyp zurückgegeben werden in Java!
Bei einem String sind das im Endeffekt char... Du könntest mein Beispiel noch endlos weiter führen. Das ist nur ein Beispiel, wo auf zweiter ebene schon ein int steht. Das könnte auch ein String sein!

Interfaces bieten hier auch keinen richtigen Schutz, denn niemand könnte einen daran hindern das Objekt zu casten, das muss schon der Zugriffsmodifizierer machen.
In diesem Fall schon, denn es kann keine andere Klasse auf die Inner-class 'ConstObject' von ConstFinally casten!

- Eth

P.S.
Kann man in C++ nicht auch so komische Dinge tun wie const auf nicht-const casten, usw... ??

EDIT: Hier mal ein Beispiel wie damit umgegangen wird:
public static void main(String[] args){
ConstFinally cf = new ConstFinally();
ImmutableObject mo = cf.gibConstObject();
System.out.println(mo.getValue());
}
Es ist in diesem Code an keiner Stelle möglich den Wert des in cf gespeicherten Objektes zu ändern, obwohl es als Referenz zurückgegeben wird!

So schnell lasse ich mich nicht davon abbringen ;-)
Wenn es jemand schafft 'co' in einem ConstFinally-Objekt zu ändern, ohne eine ConstFinally-Methode aufzurufen, dann will ich bitte den Code sehen.

EDIT2:
Nun geht es auch nicht mehr in einer abgeleiteten Klasse...

grakaman
2004-03-12, 22:22:58
Das geht doch aber in dem Fall nur, weil der zurückgegebene int Wert ein Wertetyp ist und damit sowieso eine Kopie zurückgegeben wird. Ansonsten könnte ich ja ganz einfach mit:

cf.gibConstObject().getValue().value

darauf zugreifen, falls es sich um irgend ein anderes Objekt handelt. Da ich mich nicht mit Java auskenne, fällt mir jetzt keins auf anhieb ein. Nehmen wir mal als Bsp. einen StringBuilder bei .NET. Wenn du den zurücklieferst, könnte ich das Objekt trotzdem noch verändern.
Der Gast hat schon recht, richtig schützen kann man es wohl nur mit einem readonly oder so etwas. Aber dann kann man nur beim Initialisieren das Objekt bearbeiten. Ob so etwas generell mit C++ anders geht, weiß ich allerdings nicht.

grakaman
2004-03-12, 22:44:08
Und normalerweise ist ja deine "protected SetValue" Methode eh public, sonst ergäbe es keinen Sinn, generell eine Methode zu implementieren, wenn ja eh niemand außerhalb der Klasse (oder abgeleiteten) darauf zugreifen kann. Und dann kann man ohne Probleme mit der Methode den Wert verändern.

El Fantastico
2004-03-12, 22:46:07
Original geschrieben von Gast
Meisten sind Java-"Programmierer" die gleichen Leute, welche sich auch "Web-Programmierer" schimpfen, weil sie mal mit Frontpage ne HTML-Seite erstellt haben.

http://www.heise.de/newsticker/foren/go.shtml?read=1&msg_id=5280990&forum_id=53993

:D Das hab ich doch vorhin haargenau so im Heiseforum gelesen. Bist Du es, Penko?

Einige Leute haben auch Hobbies ;)

ethrandil
2004-03-12, 22:50:26
Original geschrieben von grakaman
Und normalerweise ist ja deine "protected SetValue" Methode eh public, sonst ergäbe es keinen Sinn, generell eine Methode zu implementieren, wenn ja eh niemand außerhalb der Klasse (oder abgeleiteten) darauf zugreifen kann. Und dann kann man ohne Probleme mit der Methode den Wert verändern.
"protected setValue" ist eine Inner-Class, d.h. sie ist innerhalb einer anderen Definiert.

setValue kann man auch innerhalb der 'Vater-Klasse' aufrufen. (siehe action() ) Hat also durchaus seine Berechtigung.

Aber du hast Recht. Im Prinzip ist das ganze nur eine geschickte Verteilung von Zugriffsrechten! Nichts anderes ist const auch...

- Eth

grakaman
2004-03-12, 23:10:22
Original geschrieben von ethrandil
"protected setValue" ist eine Inner-Class, d.h. sie ist innerhalb einer anderen Definiert.

setValue kann man auch innerhalb der 'Vater-Klasse' aufrufen. (siehe action() ) Hat also durchaus seine Berechtigung.


Du kannst also in Java die SetValue Methode des ConstObject auch in der ConstFinally Klasse aufrufen? Bei C# geht das leider nicht, da ich sowas auch schon mal machen wollte.

ethrandil
2004-03-12, 23:20:40
Original geschrieben von grakaman
Du kannst also in Java die SetValue Methode des ConstObject auch in der ConstFinally Klasse aufrufen? Bei C# geht das leider nicht, da ich sowas auch schon mal machen wollte.
Jupp. Das geht :)

Und na unseren ThreadTroll vom Anfang... Hier kommt korrekter C-Code, achtung, Falle *g*:


const char *msg="don't touch!";
unsigned char *p=(unsigned char*) msg;

Tja - also - ich finde Java ist da sicherer *g*

- Eth

HellHorse
2004-03-13, 00:57:57
Weiss gar nicht, was ihr habt? Java hat ja const :D
http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308

Original geschrieben von grakaman
Du kannst also in Java die SetValue Methode des ConstObject auch in der ConstFinally Klasse aufrufen? Bei C# geht das leider nicht, da ich sowas auch schon mal machen wollte.
Geht sogar, wenn sie private wäre :(

Das, was das OO kaputt macht, ist dass die Wertetpyen eben keine Objekte sind.

Gnafoo
2004-03-13, 12:03:57
@Ethrandils Post
Nur mal so eine Frage am Rande.

Müsste das nicht:

const char msg[]="don't touch!";
unsigned char *p=(unsigned char*)msg;


heißen ? Oder ist das mit * statt [] korrekt und ich denke nur das sei falsch ? :D

cu DerTod2k

ethrandil
2004-03-13, 12:22:28
Original geschrieben von Der Tod Müsste das nicht:

const char msg[]="don't touch!";
unsigned char *p=(unsigned char*)msg;


heißen? Oder ist das mit * statt [] korrekt und ich denke nur das sei falsch?
Ich denke das ist fast identisch :)

Aber eigentlich muss ich sagen, dass ich es nicht weiß, denn ich habs nur aus einem Artikel abgeschrieben...

- Eth

Trap
2004-03-13, 14:26:58
Original geschrieben von ethrandil

const char *msg="don't touch!";
unsigned char *p=(unsigned char*) msg;

Tja - also - ich finde Java ist da sicherer *g*

Typecasts sind in C immer unsicher, in dem speziellen Fall dürfte das Programm bei den meisten Compilern beim ersten Schreibzugriff abstürzen.

In gutem C++ verwendet man keine char* und keine C-Typecasts.

ethrandil
2004-03-13, 14:42:21
Original geschrieben von Trap In gutem C++ verwendet man keine char* und keine C-Typecasts.
Aber man kann die Leute nicht davon abhalten, richtig?

Also, da lob ich mir Java, das ist wenigstens eindeutig *g*

ScottManDeath
2004-03-13, 17:24:51
bezüglich templates:

In Böses Jot-Wort Version 1.5 gibt es Generics, ein etwas eingeschränkte Version der Templates. Man spart sich beim nutzen eines containers das Casten von Object auf den konkreten Typ. Der Compiler fügt diese Casts implizit ein, die VM wird nicht geändert. Eine List<string> wird als List vom typ Object verwaltet.Nachteil: Über Reflection kommt man nicht mehr auf den Typ zurück.

In .NET 2.0 wird es auch Generics geben. Diese werden für Wert Typen extra compiliert, man bekommt den Performance Vorteil da die Elemente nicht wie bei dem bösen Jot-Wort geboxt werden, also nicht mehr solche Gymnastik wie container.AddElement(new Integer (9)); sondern einfach container.AddElement(9);

HellHorse
2004-03-13, 23:33:24
In Böses Jot-Wort Version 1.5 gibt es autoboxing (für die, die es toll finden). Es ist also nicht mehr solche Gymnastik wie container.addElement(new Integer (9)) nötig, sondern einfach container.addElement(9).
Wenn ich mich richtig erinnere, muss es aber container<Integer> sein. Container<Number> oder Container<Object> geht nicht.

Original geschrieben von ScottManDeath
Nachteil: Über Reflection kommt man nicht mehr auf den Typ zurück.

Wie jetzt? Wenn sagt List<T> reicht, aber dann doch mehr wissen will?

Trap
2004-03-14, 00:51:53
Original geschrieben von ethrandil
Aber man kann die Leute nicht davon abhalten, richtig?

Also, da lob ich mir Java, das ist wenigstens eindeutig *g*
Man kann "die Leute" in keiner Programmiersprache davon abhalten Scheiße zu programmieren. In Java sieht diese Scheiße halt etwas anders aus als in C++ und funktioniert auf andere Weise nicht wie gedacht...

Ich mag Java nicht. Es ist kaum anders und noch weniger besser als C++ und alle stürzen sich drauf als wär es die Erlösung...

ScottManDeath
2004-03-14, 16:55:23
Bei Java kommt man mit Reflection nur auf List, aber nicht mehr auf den Typ T zurück, kann also zur Laufzeit keine generic Objekte unterschiedlichen Typs zusammenbauen.