PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Was genau ist eigentlich Featherweight Java?


Senior Sanchez
2006-07-14, 17:33:47
Hoi,

Ich weiß, rtfm gilt, aber den einzig sinnvollen Aufsatz den ich darüber gefunden habe (und auf den auch alle Rezitenten verweisen) ist mir für den Freitag einfach zu lang.

Kann mir deshalb jemand kurz und knapp (oder auch gerne länger) erklären, was Featherweight Java jetzt eigentlich ist?

Es ist doch eine Art Typensystem oder?

HellHorse
2006-07-14, 22:01:08
Es ist ein Kalkül für das Java Typsystem. Damit lassen sich Aussagen über das Java Typssystem formulieren. Es wurde für generics geschaffen um zu beweisen, dass das für Java 1.5 angedachte Typsystem sound und complete ist. Dabei wurde festgestellt, dass das bei 1.0 - 1.4 nicht der Falll war und so kamen contravariante Argumenttypen und covariante Rückgabetypen in 1.5.
Ich muss nicht erwähnen, dass das Ganze nach Uni stinkt, oder?

Senior Sanchez
2006-07-14, 22:05:49
HellHorse[/POST]']
Ich muss nicht erwähnen, dass das Ganze nach Uni stinkt, oder?

Nee, brauchste nciht, das habe ich gemerkt ;)

Featherweight Java ist somit praktisch nur ein theoretisches Konstrukt um zu prüfen dass die Generics sound und complete (heißt das soviel wie abgerundet, sicher etc.) sind? Ich dachte das wäre eine Art subsystem was in die VM oder eher den Compiler reingezogen wurde um Generics irgendwie besser abzubilden.

Aber da habe ich mich wohl getäuscht.

Was sind denn contravariante Argumenttypen und covariante Rückgabetypen? Das hat sicherlich was mit Generics zu tun oder?

Monger
2006-07-14, 22:32:08
Iiih, Sprachtheorie!

Wobei ich das mit Contravarianten und Covarianten Typen noch nicht ganz verstanden habe.

Covariant heißt, dass eine Methode die eine andere überlädt, einen spezifischeren Typ als die überladene Methode zurückgeben darf, richtig?

Und andersrum: Die Argumente in der Methode dürfen einen allgemeineren Typen haben als die der überladenen Methode.

Ersteres leuchtet mir noch einigermaßen ein, aber das zweite kommt mir irgendwie spanisch vor.

Senior Sanchez
2006-07-14, 23:47:57
Monger[/POST]']Iiih, Sprachtheorie!

Wobei ich das mit Contravarianten und Covarianten Typen noch nicht ganz verstanden habe.

Covariant heißt, dass eine Methode die eine andere überlädt, einen spezifischeren Typ als die überladene Methode zurückgeben darf, richtig?

Und andersrum: Die Argumente in der Methode dürfen einen allgemeineren Typen haben als die der überladenen Methode.

Ersteres leuchtet mir noch einigermaßen ein, aber das zweite kommt mir irgendwie spanisch vor.

Hmm, wenns wirklich so ist, gehts mir genauso wie dir. Covariant würde ich ja dann sinnvoll ansehen, aber contravariante Argumente? Das ist doch schwachsinnig oder?
super() Aufrufe wären ja dann in einer entsprechenden Methode zwangsläufig gar nicht mehr möglich und allgemein sehe ich da keinen Sinn drin.


Aber moment, meinst du überladen (overloading) oder überschreiben? Da ist ja ein wichtiger Unterschied.

Monger
2006-07-15, 00:35:14
Senior Sanchez[/POST]']
Aber moment, meinst du überladen (overloading) oder überschreiben? Da ist ja ein wichtiger Unterschied.
Was meinst du mit Überschreiben? :| Ich kenne nur überladen (override) und implementieren (implement).

Anyway, ich hab grad mal gegoogelt:
http://mindprod.com/jgloss/contravariance.html

Ich kann aber keinen Hinweis darauf finden, dass Java inzwischen Contravarianz unterstützt.

Senior Sanchez
2006-07-15, 00:39:27
Monger[/POST]']Was meinst du mit Überschreiben? :| Ich kenne nur überladen (override) und implementieren (implement).

Anyway, ich hab grad mal gegoogelt:
http://mindprod.com/jgloss/contravariance.html

Ich kann aber keinen Hinweis darauf finden, dass Java inzwischen Contravarianz unterstützt.

Überladen ist die Verwendung eines Methodennames, aber es gibt mehrere mögliche Implementierungen in einer Klasse die sich in ihrer Signatur unterscheiden.

Überschreiben ist quasi die Reimplementierung einer Methode in einer Unterklasse, bei der die Signatur eben gleich bleiben muss, aber der Inhalt sich ändert.

PH4Real
2006-07-15, 01:57:03
Contravarianz ist ganz nützlich bei generischen Typen und wird auch afaik in Java nur in bei denen unterstützt.

Beispiel geordneter Baumknoten:
class Node<T extends Comparable<T>>
würde von Comparable abgeleitete Klassen nicht als Typargument akzeptieren.

Mit
class Node<T extends Comparable<? super T>>
klappt dann auch dieses Beispiel:

class A implements Comparable<A> {...}

class B extends A {...}

Node<A> nA; // funktionert
Node<B> nB; // funktioniert dank Contravarianz auch

HellHorse
2006-07-15, 11:12:33
Ich habe Müll geschrieben, contravariante Argumenttypen stehen in Java nicht zur Verfügung, weil sie mit overloading in Konkurrenz stehen.

Senior Sanchez[/POST]']
Featherweight Java ist somit praktisch nur ein theoretisches Konstrukt um zu prüfen dass die Generics sound und complete (heißt das soviel wie abgerundet, sicher etc.) sind?
Nicht die Generics, sondern das Typsystem inklusive genercis.
Senior Sanchez[/POST]']
Was sind denn contravariante Argumenttypen und covariante Rückgabetypen? Das hat sicherlich was mit Generics zu tun oder?
Nö, hat nichts mit generics zu tun und hätte auch schon in 1.0 sein sollen.

Gegeben ein Typ T mit einer Methode m deren Argumenttyp A und deren Rückgabetyp R ist. Dann ist S ein Subtyp von T falls er eine Methode m aufweist deren Argumenttyp A oder ein Supertyp davon und deren Rückgabetyp R der ein Subtyp davon ist.

Das ist Typtheorie und steht nicht zur Diskussion.

Das stellt sicher, dass jedes Objekt von Typ T eine Methode m hat, die mit einem Typ Argument vom Typ A aufgerufen werden kann und ein Objekt vom Typ R zurückgibt.

Eine Sprache von einem angesehenen Professor in Zürich, der unglaublich von sich und seiner Sprache überzeugt ist, hat covariante Argumenttypen. Da ist obiges nicht gegeben. Du hast dann zwar ein statisches Typsystem, weisst aber nicht, ob die Argumenttypen stimmen. :uup:

Beispiel das in Java nicht geht:

public interface I {
public Object m(String key);
}


public class T implements I {
public Integer m(Object key) {
return key.hashCode();
}
}

#m S implementiert I nicht weil der Argumenttyp contravariant ist, ist also auch nicht vom Typ I oder einem Subtyp davon. Dass der Rückgabetyp contravariant ist, spielt ab 1.5 keine Rolle mehr, vorher war das ein Problem.

Senior Sanchez
2006-08-05, 02:06:36
Beispiel das in Java nicht geht:

public interface I {
public Object m(String key);
}


public class T implements I {
public Integer m(Object key) {
return key.hashCode();
}
}

#m S implementiert I nicht weil der Argumenttyp contravariant ist, ist also auch nicht vom Typ I oder einem Subtyp davon. Dass der Rückgabetyp contravariant ist, spielt ab 1.5 keine Rolle mehr, vorher war das ein Problem.

Ist der Rückgabetyp an dieser Stelle von T nicht covariant statt contravariant wie du es schreibst? Integer extended doch Object und nicht umgekehrt.

HellHorse
2006-08-05, 09:35:46
Ist der Rückgabetyp an dieser Stelle von T nicht covariant statt contravariant wie du es schreibst?
Ooops, natürlich :redface:

Senior Sanchez
2006-08-05, 10:12:09
Ooops, natürlich :redface:

kein problem, dann habe ich das soweit verstanden.

Nur mit dem Generics-Beispiel von php4real tue ich mich noch schwer.

HellHorse
2006-08-05, 12:53:44
kein problem, dann habe ich das soweit verstanden.
Ich will nicht dein Hilfsassistent sein ;)

Nur mit dem Generics-Beispiel von php4real tue ich mich noch schwer.
Hat aus meiner Sicht mit lower bounds für wildcards und nicht mit contravarianz zu tun. Muss aber nicht stimmen, hab's erst zweimal duchgedacht.

Verdammt, statische Typsysteme, genercis, echt jetzt. Manchmal habe ich das Gefühl, dass Leute, die statische Typsysteme befürworten, sie nicht begriffen haben.

Senior Sanchez
2006-08-05, 13:10:07
Ich will nicht dein Hilfsassistent sein ;)

Keine Sorge, biste nicht :) Bist hier eh einer meiner Götter, an die ich vom Wissen erstmal heranreichen muss. Aber wenn man nicht lernt, kommt man auch nicht weiter. Daher meine Fragerei *g*


Verdammt, statische Typsysteme, genercis, echt jetzt. Manchmal habe ich das Gefühl, dass Leute, die statische Typsysteme befürworten, sie nicht begriffen haben.

Sind Generics ansich nicht eigentlich bloß ne Bastellösung um dem statischen Typsystem eine dynamische Komponente zu verleihen oder bin ich aufm Holzweg?

Weil das Merkmal statischer Typisierung ist doch, dass zur Übersetzungszeit feststeht, um was für einen Typen es sich bei einer bestimmten Variable handelt. Bei einem dynamischen Typsystem steht das doch dagegen erst zur Ausführungszeit fest.

Und Generics wären dann meinem Verständnis nach ne Krücke um dem statischen System Dynamik zu verleihen und Algorithmen eben generischer zu machen.


Was gefällt dir daran nicht?

Monger
2006-08-05, 13:29:07
Sind Generics ansich nicht eigentlich bloß ne Bastellösung um dem statischen Typsystem eine dynamische Komponente zu verleihen oder bin ich aufm Holzweg?

Es ist noch viel schlimmer. Generics sind ein reiner Compiler Hack, zur Laufzeit sind die schon längst rausrationalisiert und durch normale Casts ersetzt.

Im Prinzip sind sie ein kleverer (allerdings nicht vollständiger) Ersatz für Casts, mehr nicht. An Generics ist rein gar nichts dynamisch.

Trap
2006-08-05, 13:36:10
Generics sind einfach higher-order types. Genauso wie bei den Funktionen sind auch die higher-order Typen genauso ausdrucksstark wie normale Typen.

Eigentlich ganz lustig, dass man higher-order types einbaut, aber higher-order functions rauslässt :tongue:

Statische Typsysteme haben unter anderem den Nachteil: Sie verhindern auch, dass gültige Programme, die nur nicht bewiesen werden können, ausgeführt werden können.
Ohne Typinferenz sind sie außerdem Arbeit für die Programmierer und erhöhen die "Trägheit des Sourcecodes".

Weil das Merkmal statischer Typisierung ist doch, dass zur Übersetzungszeit feststeht, um was für einen Typen es sich bei einer bestimmten Variable handelt. Bei einem dynamischen Typsystem steht das doch dagegen erst zur Ausführungszeit fest.
Welche Typen eine Variable annehmen kann ist völlig unabhängig vom annotierten Typ und steht für alle Programmiersprachen (auch für dynamische) zur Ausführungszeit fest. Dummerweise dürfte diese Eigenschaft nicht berechenbar sein.

Senior Sanchez
2006-08-05, 13:58:12
Es ist noch viel schlimmer. Generics sind ein reiner Compiler Hack, zur Laufzeit sind die schon längst rausrationalisiert und durch normale Casts ersetzt.

Im Prinzip sind sie ein kleverer (allerdings nicht vollständiger) Ersatz für Casts, mehr nicht. An Generics ist rein gar nichts dynamisch.

Stimmt, genau, ich vergaß. Das hatte ich auch schonmal gelesen, dass die Generics im Grunde nur nen Hack sind. Somit müsste ja reintheoretisch auch mit 1.5 kompilierter Sourcecode (= Bytecode ;) ) auf ner älteren VM laufen, richtig?

@Trap
Was sind higher-order Types und higher-order Functions?

Was ist dann der Unterschied zwischen dynamischen und statischen Typsystemen?

Ich meinte jetzt im Bezug zur Ausführungszeit, dass einige Programmiersprachen doch son Variant-Typen haben, der sich mit beliebigen Daten füllen lässt, sei es numerisch, alphanumerisch oder whatever. Das entscheidet sich doch dann erst zur Ausführung welchen Typ diese Variable eigentlich annimmt, also ob Integer, Float oder whatever.

Trap
2006-08-05, 14:29:40
higher order functions sind Funktionen, die Funktionen als Parameter bekommen. Die üblichen Beispiele dafür sind map, reduce oder der Y-combinator.

higher order types sind Typen, die Typen als Parameter bekommen. Es gibt auch noch eine andere Variante von Typen, dependent types, die bekommen Werte als Parameter, z.B. sowas wie List[3], als Liste mit 3 Elementen. Ich bin mir aber recht sicher, dass "higher order types" nicht der übliche Begriff dafür ist.

Der Unterschied ist einfach, dass statische Typprüfung dafür sorgt, dass bestimmter Code beim Kompilieren eine Fehlermeldung erzeugt, was es bei dynamischen Typsystemen nicht gibt.

Ich meinte jetzt im Bezug zur Ausführungszeit, dass einige Programmiersprachen doch son Variant-Typen haben, der sich mit beliebigen Daten füllen lässt, sei es numerisch, alphanumerisch oder whatever. Das entscheidet sich doch dann erst zur Ausführung welchen Typ diese Variable eigentlich annimmt, also ob Integer, Float oder whatever.
Solange der Typ von Variablen nicht von Eingaben an das Programm abhängt kann man für jeden Ausführungspfad des Programms exakt bestimmen welchen Typ welche Variable zu jedem Zeitpunkt hat, im einfachsten Fall mit durchsimulieren und nachgucken.
In den Fällen wo es von Eingaben abhängt kann man es für jede mögliche Äquivalenzklasse von Eingaben machen.

So ein Verfahren hat allerdings einige praktische Probleme:
-nicht terminierende Funktionen (einfach 10 Jahre Laufzeit simulieren, das reicht für 99% der Programme ;))
-es kann extrem viele mögliche Ausführungspfade geben
-es kann extrem viele Äquivalenzklassen von Eingaben geben

Ist halt ein theoretisches Konzept, keine Implementierungsmöglichkeit für ein Typsystem.

Monger
2006-08-05, 15:40:37
Stimmt, genau, ich vergaß. Das hatte ich auch schonmal gelesen, dass die Generics im Grunde nur nen Hack sind. Somit müsste ja reintheoretisch auch mit 1.5 kompilierter Sourcecode (= Bytecode ;) ) auf ner älteren VM laufen, richtig?

Tun sie afaik auch. In 1.5 ist nix drin, was nicht auch auf einer alten VM laufen würde.

HellHorse
2006-08-05, 18:34:05
Sind Generics ansich nicht eigentlich bloß ne Bastellösung um dem statischen Typsystem eine dynamische Komponente zu verleihen oder bin ich aufm Holzweg?
Nö, wie schon erwähnt existieren Generics eigentlich nur zur Kompilationszeit. Sind also so statisch wie nur irgend möglich.
Weil das Merkmal statischer Typisierung ist doch, dass zur Übersetzungszeit feststeht, um was für einen Typen es sich bei einer bestimmten Variable handelt. Bei einem dynamischen Typsystem steht das doch dagegen erst zur Ausführungszeit fest..
Ja.

Was gefällt dir daran nicht?
Nicht triviale Beispiele zerlegen mir das Gehirn. Regelmässig. Siehe dazu auch:
http://www.forum-3dcenter.org/vbulletin/showthread.php?t=289631

Das einzige (ausserhalb der jeweiligen Problemdomäne), das mir je so das Hirn zerlegte war die Smalltalk Metaklassenhierarchie.

Stimmt, genau, ich vergaß. Das hatte ich auch schonmal gelesen, dass die Generics im Grunde nur nen Hack sind. Somit müsste ja reintheoretisch auch mit 1.5 kompilierter Sourcecode (= Bytecode ) auf ner älteren VM laufen, richtig?
Ja theoretisch. gj ist ja auch für 1.4 (oder sogar noch älter).
In der Praxis wird das durch die Versionsnummer verhindert. Aber auch Stringkontatentation verwendet in 1.5 StringBuilder, den es in 1.4 noch nicht gibt. Zudem gibt es ja auch Annotationen, die im Bytecode bleiben können. Bei enums bin ich mir nicht sicher, ob die in ganz normale Klassen und statische Felder kompilert werden, oder ob es da noch etwas Magie gibt.

Eigentlich ganz lustig, dass man higher-order types einbaut, aber higher-order functions rauslässt :tongue:
Naja, functions sind ja keine first class objects. Von dem her geht das ja nicht. Du musst halt eben ein Objekt (und daher notwendigerweise auch eine Klasse) machen, die eine Funktion repräsentiert. Ja, elegant ist anders. Aber es gibt ja diverse funktionale Frameworks für Java.


Ohne Typinferenz sind sie außerdem Arbeit für die Programmierer und erhöhen die "Trägheit des Sourcecodes".
Ja, bloss hat Typinferenz genauso Lücken in denen man von Hand die Typen angeben muss.

Ich meinte jetzt im Bezug zur Ausführungszeit, dass einige Programmiersprachen doch son Variant-Typen haben, der sich mit beliebigen Daten füllen lässt, sei es numerisch, alphanumerisch oder whatever. Das entscheidet sich doch dann erst zur Ausführung welchen Typ diese Variable eigentlich annimmt, also ob Integer, Float oder whatever.
Oder man macht einfach alles ein Objekt. Dann hätte man nicht VARIANT, OBJECT und die Sachen, die weder VARIANT noch OBJECT sind wie byte arrays.