Der Zwiespalt: low or high



  • Hallo liebe Community,

    ich stehe an einem Punkt der mir garnicht passt, ich habe mich mit C++ beschäftigt und um eine höhere Sprache kennen zu lernen auch ein bisschen mit C#/Python. Jetzt muss ich mich entscheiden, entweder tiefer in die Linuxprorgrammierung eingehen (ich habe kein windows), C gehört dann natürlich auch dazu, oder mit einer höheren Sprache weitermachen, ersteres fände ich spannender aber lohnt sich der Aufwand noch?
    Ich will damit keinen Flame außlösen, aber werden in Zukunft low level Sprachen mehr an Wert verlieren - und alles wäre umsonst? Wenn ich mich da in der Linux Umgebung angucke domentiert C/C++ aber auf jeden Fall!

    Die Zweite Möglichkeit jetzt ist es mit Python etc. enduseranwedungen zu schreiben.

    Dieser Zwiespalt lässt mich fast verrückt werden, vielleicht habt ihr ähnliche Situation überwunden?

    Danke 🙂



  • Ich würde an deiner Stelle erstmal ein wenig Systemprogrammierung machen, wenn du C und/oder C++ schon gut kannst. Dann kannst du nämlich dein System mal ein wenig kennen lernen und verstehst eher warum was wie abläuft (auch bei Hochsprachen). Du musst natürlich kein Überprofi in dem Bereich werden, es geht hauptsächlich um das Verständniss. Auch Assemblerprogrammierung kann nicht schaden.

    Hochsprachen solltest du natürlich aber auch nicht vernachlässigen, aber die sind doch leichter zu beherschen, wenn du bereits C kannst, da die populären Sprachen relativ viel C kopieren. Das arbeiten damit fällt natürlich deutlich leichter, als die LowLevel Dinge.

    Also => Mach die gute Mischung aus beidem. Ohne LowLevel-Wissen wirst du IMHO kein guter Programmierer und HighLevel-Wissen ist idr. im Beruf gefragter.



  • Eigentlich schreibe ich nur noch C++.
    Da ich pures C aber auch irgendwie mag, schaue ich gerne hier im ANSI C nach und helf mal ab und zu Leuten, die C proggen "müssen" 😉



  • kingruedi schrieb:

    Ich würde an deiner Stelle erstmal ein wenig Systemprogrammierung machen, wenn du C und/oder C++ schon gut kannst. Dann kannst du nämlich dein System mal ein wenig kennen lernen und verstehst eher warum was wie abläuft (auch bei Hochsprachen). Du musst natürlich kein Überprofi in dem Bereich werden, es geht hauptsächlich um das Verständniss. Auch Assemblerprogrammierung kann nicht schaden.

    Hochsprachen solltest du natürlich aber auch nicht vernachlässigen, aber die sind doch leichter zu beherschen, wenn du bereits C kannst, da die populären Sprachen relativ viel C kopieren. Das arbeiten damit fällt natürlich deutlich leichter, als die LowLevel Dinge.

    Also => Mach die gute Mischung aus beidem. Ohne LowLevel-Wissen wirst du IMHO kein guter Programmierer und HighLevel-Wissen ist idr. im Beruf gefragter.

    Vielen dank, für die Antwort. So einen Ruck habe ich gebraucht 👍
    Das viele "moderne" sprachen ihre Wurzeln in C/C++ haben habe ich mir auch schon gedacht, so ist es logisch das man diese hohen sprachen dann leichter lernt wenn man die Wurzlen kennt 😋



  • Ich meine aus deinen Postings heraus zu lesen, dass du C++ als lowlevel-Sprache siehst, richtig? Vielleicht solltest du erstmal erklären, was du unter einer lowlevel- bzw. highlevel Sprache verstehst, weil C++ ist definitiv eine höhere Sprache.



  • MaSTaH schrieb:

    Ich meine aus deinen Postings heraus zu lesen, dass du C++ als lowlevel-Sprache siehst, richtig? Vielleicht solltest du erstmal erklären, was du unter einer lowlevel- bzw. highlevel Sprache verstehst, weil C++ ist definitiv eine höhere Sprache.

    Ja, das ist sie, aber nicht so wie C# oder Python 🙂
    War vielleicht ein bisschen blöd formuliert, eigentlich meine ich mit LowLevel schon C.



  • C++ würde ich nicht unbedingt als unmodern Bezeichnen. Du musst dringend zwischen C++ und C unterscheiden lernen. Ein gutes C++ Programm hat eigentlich nichts mehr mit C zu tun.

    <edit>ups, ich seh gerade, das MaSTaH das schon angesprochen hat. War irgend wie blind</edit>



  • Hi ogb,

    auch wenn man sich mit "höheren" Sprachen wie Python vorwiegend beschäftigt, ists doch kein fehler auch C zu können. Ich hab mir z.B. auch schon das eine oder andere Modul für Python in C geschrieben. Zu vielen Libraries bekommst Du leicht Informationen für C oder C++, dann ist es gut wenn du das zumindest lesen kannst um es dann z.B. in Python umzusetzen.
    Python hat halt, für mich ein paar entschedende Vorteile: Kein Compilieren nötig, keine Speicherzugriffsfehler, meist recht aussagekräftige Fehlermeldungen, "Batteries included", ...
    Ich würde weiterhin zweigleisig fahren und jeweils abhängig von den Anforderungen entweder C oder Python oder halt beides verwenden.

    Gruß

    Dookie



  • kingruedi schrieb:

    C++ würde ich nicht unbedingt als unmodern Bezeichnen. Du musst dringend zwischen C++ und C unterscheiden lernen. Ein gutes C++ Programm hat eigentlich nichts mehr mit C zu tun.

    ...außer den unzähligen Altlasten, die es mitschleppt. Oder gibt es schon einen modernen Ersatz für das unsägliche Modell der getrennten Übersetzung?



  • Ich würde C++ schon als unmodern bezeichnen. Disclaimer: Soll keinen Flamewar auslösen, stellt aber meine persönliche Meinung dar, die ich haben darf.
    Das Übersetzungsmodell ist extrem unmodern, der Compiler ist dumm wie ein Stück Brot.
    Die Standardbibliothek ist auch unmodern. Ja, ich kenne das Standard-Argument, in C++ nimmt man externe Bibliotheken blabla. Aber wenn selbst grundlegende I/O Sachen wie weitergehende Unicode-Unterstützung oder Sockets fehlen, kommt mir das unmodern vor.
    Gefragt ist C++ trotzdem, das will ich ja nicht absprechen. Aber deshalb ist es nicht modern. C++ selber ist schon recht alt und die C-Lasten, die es noch mitschleppt, sind Steinalt.



  • ich versteh nicht wieso es einen unterschied macht, ob man eine externe lib benutzen muss, falls man diese dinge braucht die du ansprichts, oder ob das alles bereits in der sprache intergriert ist. imho macht es mehr sinn sowas in externe libs zu lagern, weil das nicht wirklich ist, das jeder unbedingt haben muss.
    mit den C lasten haste recht 😉
    und den compiler müsste man wirklich verbessern



  • imho macht es mehr sinn sowas in externe libs zu lagern, weil das nicht wirklich ist, das jeder unbedingt haben muss.

    roflmao. Willkommen im Jahr 2005. Ne, Unicode ist verdammt wichtig, jetzt schon und für die Zukunft auch. Und es suckt einfach, das WinAPI bemühen zu müssen um Unicode in eine Datei zu kriegen.

    und den compiler müsste man wirklich verbessern

    Die Compiler an sich sind gut. Dass sie so dumm sind, ist aufgrund des Übersetzungsmodells unvermeidlich. Das abzuschaffen ist aber eine so grundlegende Änderung, dass sie C++ IMHO nie erleben wird.
    Man kann zwar schon damit leben. Aber es ist einfach irgendwie schöner, alles direkt zu coden und direkt ändern zu können, nicht immer an mindestens 2 Stellen.

    Änderungen tun verdammt weh. Auch in Java hat man das Problem bereits ein bisschen. Du kannst heute auf ner aktuellen VM jeden Bytecode ausführen. Solange dies geht, ist die Welt heil. Aber das ist eine riesige Hürde für Verbesserungen.



  • Optimizer schrieb:

    Ich würde C++ schon als unmodern bezeichnen.

    hmm, Features wie Templates können Java und C# ja erst langsam und dann auch weit nicht so umfangreich liefern.

    Dass das C++ Übersetzungskonzept nicht ideal ist, stimmt auch. Aber das liegt nicht an C++, sondern an den Implementierungen. So sieht der Standard ja die Möglichkeiten vor, dass man das auch anders regelt. Der Visual Age Compiler von IBM hatte das wohl mit Modulen, der ist aber leider der einzige, den ich kenne.

    Die Standardlibrary ist leider auch sehr dürftig. Aber ich muss sagen, dass boost da schon einiges rausholt.

    Ich hoffe mal auf C++0x, wenn das irgend wann kommt.

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1736.pdf

    und einheitlicher Unicode-Support inklusive Multibyte-Zeichensätze will ich auch haben 🙂



  • kingruedi schrieb:

    hmm, Features wie Templates können Java und C# ja erst langsam und dann auch weit nicht so umfangreich liefern.

    Da wäre ich vorsichtig. Wir müssen sicher nicht diskutieren, ob Java, C# oder C++ am umfangreichsten ist. Tatsache ist aber, dass diese Einschränkungen, die Generics gegenüber Templates beabsichtigt sind, bzw. Generics eigentlich ein anderes Konzept sind.

    Generische Klassen und Methoden kennen die Anforderungen an ihre Typparameter. Bei C++ wird einfach mal alles eingesetzt, 50mal umg3h4x0r7 und irgendwann stellt der Compiler fest, dass er nicht weiß, wie er zwei FooBars addieren muss (passt zum restlichen Übersetzungsmodell 😉 ).

    Ich würde deshalb eher davon absehen, diese beiden Dinge zu vergleichen. Mir reicht auch die Flexibilität von Generics völlig aus. Das Problem an C++ ist IMHO, dass es versucht, alles zu sein.
    Um zum Thema zurückzukommen: Du müsstest jetzt eigentlich begründen, dass Templates moderner sind als Generics, nicht umfangreicher.



  • Du müsstest jetzt eigentlich begründen, dass Templates moderner sind als Generics, nicht umfangreicher.

    Moderner bedeutet ja etwas zeitliches 🙂 Templates sind auch sicher nicht das wichtigste an einer Sprache, wenn auch ein cooles Feature, wie zB. boost eindrucksvoll zeigt.

    http://www.artima.com/intv/generics.html <-- interessantes Gespräch zwischen Bruce Eckel, Bill Venners und Anders Hejlsberg



  • Optimizer schrieb:

    Generische Klassen und Methoden kennen die Anforderungen an ihre Typparameter. Bei C++ wird einfach mal alles eingesetzt, 50mal umg3h4x0r7 und irgendwann stellt der Compiler fest, dass er nicht weiß, wie er zwei FooBars addieren muss (passt zum restlichen Übersetzungsmodell 😉 ).

    Was natürlich blödsinn ist. Denn in C++ hat man die Möglichkeit von Concept Checks - in C#/Java werden sie automatisch eingefügt.

    Ich weiss nicht wie es in Java ist, aber in C# kann man es genauso wie in C++ machen - nur dass es dort eben dynamisch ist. Ich kann ja einfach das Object zu einem Interface casten (egal ob das Objekt dieses Interface implementiert oder nicht) und mir somit einen Runtime Error einfangen. Theoretisch müsste es in Java genauso gehen.

    Insofern sehe ich dein Argument als falsch an. Da ich bei Beiden (Generics und Templates) statische Concept Checks haben kann (es aber nicht muss). Es unterscheidet sich lediglich die 'Default Einstellung'.

    Ich würde deshalb eher davon absehen, diese beiden Dinge zu vergleichen.

    Mir reicht auch die Flexibilität von Generics völlig aus.

    Widerspruch?

    Klar sind Generics etwas anderes als Templates - Generics sollten ja nie die Fähigkeiten von Templates haben. In C# kann man alles was man zur Compiletime kann auch zur Runtime machen - das schränkt natürlich die Möglichkeiten von Generics ein. Und in Java sind Generics sowieso nur ein Präprozessor-Hack.

    Um zum Thema zurückzukommen: Du müsstest jetzt eigentlich begründen, dass Templates moderner sind als Generics, nicht umfangreicher.

    Warum modern? Was hat das damit zu tun?

    C++ mag für dich unmodern sein, was teilweise natürlich auch stimmt. Aber es kommt nunmal nicht darauf an wie modern etwas ist - oder hältst du Lisp für veraltet und verstaubt? (denn modern ist es sicher nicht mehr).

    Und ist Java nicht auch unmodern geworden seitdem es .NET gibt?

    Die Java Generics mögen modern sein - sind aber trotzdem nichts anderes als ein Präprozessor-Hack, den man schon in C machen konnte (und wenn man einen präprozessor selber schreibt, kann man es mit jeder Sprache machen).



  • Ich weiss nicht wie es in Java ist, aber in C# kann man es genauso wie in C++ machen - nur dass es dort eben dynamisch ist.

    Kannst du das genauer ausführen? In C# muss man Constraints definieren, sonst kann man nur die System.Object Schnittstelle benutzen!
    Das muss man in C++ wohl keineswegs so machen. Ich kann eine sortierte Liste schreiben, und die T-Objekte mit '<' vergleichen, wie ich lustig bin.
    Wenns dann doch nicht geht, merkt der Compiler das irgendwann. In C# ist dagegen gleich klar: Wenn ich jetzt ne SortedList<T : ICompareable> benutzen will, muss meine Klasse dieses Interface implementieren.

    Ich kann ja einfach das Object zu einem Interface casten (egal ob das Objekt dieses Interface implementiert oder nicht) und mir somit einen Runtime Error einfangen. Theoretisch müsste es in Java genauso gehen.

    Ach bitte, das ist doch nicht dein Ernst. Ein Sinn der Generics ist es ja, die casts zu eliminieren, wenn ich es trotzdem mach, brauch ich die Generics nicht verwenden. Kein Mensch würde so etwas tun. (Ok, Zitat Scott Meiers: "Alles was möglich ist, wird irgendwann irgendjemand tun")

    Da ich bei Beiden (Generics und Templates) statische Concept Checks haben kann

    Nein. In Java/C# musst du sie haben. Und in C++ funktionieren sie anders. Ich habe nicht gesagt, dass C++ mehr Laufzeitfehler produziert.

    Um zum Thema zurückzukommen: Du müsstest jetzt eigentlich begründen, dass Templates moderner sind als Generics, nicht umfangreicher.

    Warum modern? Was hat das damit zu tun?

    Weil kingruedi sich ja auf meine Aussage mit modern bezogen hat. Er hat sich auf diese Aussage bezogen, aber dann ausgeführt, dass Templates umfangreicher sind. Das hat mich irritiert. 🙂

    Die Java Generics mögen modern sein - sind aber trotzdem nichts anderes als ein Präprozessor-Hack, den man schon in C machen konnte

    Oh nein!! Du solltest sie wirklich öfters benutzen. Auf Bytecode-Ebene sind sie ein Hack, das stimmt. Man wollte aus gutem Grund die VM nicht ändern.
    Aber auf Hochsprachenebene sind sie ein für Java völlig neues Sprachfeature, ein sehr mächtiges. Über das "cast vor dem Programmierer verstecken" geht das weit hinaus. Constraints an Typparameter sind sogar ein ziemlich neues, eigenes Konzept.



  • kingruedi schrieb:

    Du müsstest jetzt eigentlich begründen, dass Templates moderner sind als Generics, nicht umfangreicher.

    Moderner bedeutet ja etwas zeitliches 🙂 Templates sind auch sicher nicht das wichtigste an einer Sprache, wenn auch ein cooles Feature, wie zB. boost eindrucksvoll zeigt.

    http://www.artima.com/intv/generics.html <-- interessantes Gespräch zwischen Bruce Eckel, Bill Venners und Anders Hejlsberg

    Jo, kenn ich. 🙂
    Ich mag den Typen aber nicht mehr, seit er das über checked Exceptions gesagt hat. Er hat ganz eindeutig ein paar Konzepte von Java nicht verstanden und seine Argumentation ist äußerst fadenscheinig. Das wäre jetzt aber eher was für einen eigenen Thread...

    EDIT: Ahja, aber siehe hier, was hat der Meister gesagt: 🕶

    The big difference between C# generics and C++ templates shows up in when the type checking occurs and how the instantiation occurs. First of all, C# does the instantiation at runtime. C++ does it at compile time, or perhaps at link time. But regardless, the instantiation happens in C++ before the program runs. That's difference number one. Difference number two is C# does strong type checking when you compile the generic type. For an unconstrained type parameter, like List<T>, the only methods available on values of type T are those that are found on type Object, because those are the only methods we can generally guarantee will exist. So in C# generics, we guarantee that any operation you do on a type parameter will succeed.



  • Optimizer schrieb:

    Kannst du das genauer ausführen? In C# muss man Constraints definieren, sonst kann man nur die System.Object Schnittstelle benutzen!

    Es hindert mich aber nichts an einem
    Base b;
    ((Derived)b).derived_only_method();

    wenn ich mal keine Constraints haben will. Natürlich kommt das mit Runtime Overhead, den ich nicht hätte, wenn ich ein Concept dafür definiert hätte. Aber es ist technisch machbar und kann ja auch mal nützlich sein (wenn ich eine spezielle Implementierung für etwas haben will).

    Das muss man in C++ wohl keineswegs so machen. Ich kann eine sortierte Liste schreiben, und die T-Objekte mit '<' vergleichen, wie ich lustig bin.
    Wenns dann doch nicht geht, merkt der Compiler das irgendwann. In C# ist dagegen gleich klar: Wenn ich jetzt ne SortedList<T : ICompareable> benutzen will, muss meine Klasse dieses Interface implementieren.

    Klar, nur muss ich es eben auch in C# nicht machen, weil ich einfach nach IComparable casten kann (wenn ich lustig bin). Genauso wie ich in C++ einen Concept Check einbauen kann.

    Wie gesagt der Unterschied ist die 'Default Einstellung':
    Java/C# haben defaultmäßig Concepts
    C++ hat defaultmäßig keine Concepts

    Ach bitte, das ist doch nicht dein Ernst. Ein Sinn der Generics ist es ja, die casts zu eliminieren, wenn ich es trotzdem mach, brauch ich die Generics nicht verwenden. Kein Mensch würde so etwas tun. (Ok, Zitat Scott Meiers: "Alles was möglich ist, wird irgendwann irgendjemand tun")

    Warum?
    Ich kann doch sagen: Um meine List zu verwenden muss das Ding nicht vergleichbar sein - ausser wenn man .sort() verwendet (und ich weiss, dass man sort() normalerweise nicht braucht). Dann wäre es doof IComparable als Concept zu definieren, weil es eben nicht zwangsläufig nötig ist.

    Natürlich wird man das nicht oft brauchen (weil es eben nur für ausnahmen sinnvoll ist - aber bei diesen ausnahmen ist es eben _sehr_ sinnvoll) - aber es ist möglich. Und genau darauf weise ich hin.

    Denn Concepts sind nicht immer nur ein Vorteil - man braucht sie manchmal nicht, bzw. behindern sie einen. Denn sobald ich sage, dass ein Typ Interface A implementieren muss, dann muss es dass - auch wenn ich die Funktionalität die dadurch entsteht nicht brauche. Das IComparable ist dabei ein super Beispiel. Denn wieoft will ich eine List wirklich sortieren? Normalerweise wesentlich seltener als eine zu verwenden, oder? Wozu muss dann mein Typ IComparable implementieren? Vielleicht macht das ja auch keinen Sinn? Ich meine, nicht jede Klasse die ich handle muss einen Operator< implementieren. zB Plugin Klassen. Ich kann zwar sagen: a!=b - das ist nicht schwer, aber welches Plugin ist kleiner? Unmöglich zu sagen. Aber dennoch möchte ich 10 Plugins in eine Liste stecken.

    Wenn ich aber ints hineinstecke - dann will ich die auch sortieren können...

    Nein. In Java/C# musst du sie haben. Und in C++ funktionieren sie anders. Ich habe nicht gesagt, dass C++ mehr Laufzeitfehler produziert.

    Eben nicht.
    In Java ist es sowieso egal ob ich caste oder der Compiler. Lediglich in C# habe ich dann einen overhead - der aber für spezielle Situationen durchaus verkraftbar ist.

    Oh nein!! Du solltest sie wirklich öfters benutzen. Auf Bytecode-Ebene sind sie ein Hack, das stimmt. Man wollte aus gutem Grund die VM nicht ändern.
    Aber auf Hochsprachenebene sind sie ein für Java völlig neues Sprachfeature, ein sehr mächtiges. Über das "cast vor dem Programmierer verstecken" geht das weit hinaus. Constraints an Typparameter sind sogar ein ziemlich neues, eigenes Konzept.

    Naja, schau sie dir mal in C# an - das sind gute Generics. Klar wird es gut versteckt, aber Hack bleibt Hack. Welche möglichkeit bieten mir Java Generics denn, die ich nicht mit geringem Aufwand auch ohne Generics hinbekomme?

    ein Concept Check geht ja simpel:
    (ConceptA)obj;
    Und sonst erspart es mir nur die Casts selber zu schreiben.
    Oder übersehe ich einen wesentlichen Punkt?

    In C# sind Generics Native. Da habe ich auch noch die Typinformationen zur Runtime - kann also auch Generics zur Laufzeit erstellen usw. Da hat man wirklich neue Möglichkeiten.

    Concepts sind aber nicht wirklich so neu - oder können Java Concepts etwas, dass ich nicht kenne? Concepts sind doch ein einfaches "Pattern Matching" ala "Typ X implementiert Interface A und erbt von Klasse B".
    Concepts in C++ sind da sogar noch etwas weiter - indem eben nicht nur Typen gecheckt werden können, sondern sogar einzelne Funktionen.



  • Shade Of Mine schrieb:

    Optimizer schrieb:

    Kannst du das genauer ausführen? In C# muss man Constraints definieren, sonst kann man nur die System.Object Schnittstelle benutzen!

    Es hindert mich aber nichts an einem
    Base b;
    ((Derived)b).derived_only_method();

    wenn ich mal keine Constraints haben will. Natürlich kommt das mit Runtime Overhead, den ich nicht hätte, wenn ich ein Concept dafür definiert hätte. Aber es ist technisch machbar und kann ja auch mal nützlich sein (wenn ich eine spezielle Implementierung für etwas haben will).

    Meinst du jetzt so etwas:

    class Comparer<T>
    {
        static int compare(T a, T b)
        {
            return ((Comparable)a).compareTo((Compareable)b);
        }
    }
    

    So etwas wäre Selbstmord. Es kann dir ja niemand garantieren, dass T Compareable ist. Nein, so etwas würde man nicht machen, es ist nicht nützlich und dafür gibt es auch nie einen guten Grund. Es gibt ja nicht zum Spaß die Constraints und ich könnte die Anforderung an den Typ T stellen, dieses Interface zu implementieren.
    Spezialisierung kann ich anders viel besser erreichen:

    class NumberComparer extends Comparer<Number>     {}
    

    Klar, nur muss ich es eben auch in C# nicht machen, weil ich einfach nach IComparable casten kann (wenn ich lustig bin).

    Das ist kein Vergleich. Beim casten entlässt man immer den Compiler aus der Verantwortung. Ich betone es nochmal: So etwas würde man wie in dem Beispiel oben niemals machen. Es gibt nicht den geringsten Grund dafür.
    Das hat mit default-Einstellung nichts zu tun. Innerhalb eines generischen Typs, wo ich alle Anforderungen, die ich haben will, definieren kann, ist casten vorsätzliche Sabotage. Jeder vernünftige Compiler warnt davor.

    Warum?
    Ich kann doch sagen: Um meine List zu verwenden muss das Ding nicht vergleichbar sein - ausser wenn man .sort() verwendet (und ich weiss, dass man sort() normalerweise nicht braucht). Dann wäre es doof IComparable als Concept zu definieren, weil es eben nicht zwangsläufig nötig ist.

    Nein. Man würde eine Klasse List<T> schreiben und davon eine Klassen SortableList<T extends ICompareable> ableiten. Casten ist definitiv tabu. Das ist ja gerade der Witz. 🙂
    Wie ich jetzt z.B. auf Strings spezialisieren könnte, steht oben.

    Natürlich wird man das nicht oft brauchen (weil es eben nur für ausnahmen sinnvoll ist - aber bei diesen ausnahmen ist es eben _sehr_ sinnvoll) - aber es ist möglich. Und genau darauf weise ich hin.

    Denn Concepts sind nicht immer nur ein Vorteil - man braucht sie manchmal nicht, bzw. behindern sie einen. Denn sobald ich sage, dass ein Typ Interface A implementieren muss, dann muss es dass - auch wenn ich die Funktionalität die dadurch entsteht nicht brauche. Das IComparable ist dabei ein super Beispiel. Denn wieoft will ich eine List wirklich sortieren? Normalerweise wesentlich seltener als eine zu verwenden, oder? Wozu muss dann mein Typ IComparable implementieren? Vielleicht macht das ja auch keinen Sinn? Ich meine, nicht jede Klasse die ich handle muss einen Operator< implementieren.

    Ja. Es kann mit Constraints etwas umständlicher sein. Ist mir auch einmal schon passiert. Constraints haben nicht nur Vorteile. Vollkommen klar. Ich will auch nur sagen, dass es ein anderes Konzept ist.
    Ich persönlich finde es schöner, du kannst natürlich völlig anderer Meinung sein. Allerdings ist es btw. nicht wirklich ein Aufwand, jetzt von der List<T> abzuleiten und noch eine sort-Methode dazuzudefinieren. Das muss man schon auch mal sehen.

    Naja, schau sie dir mal in C# an - das sind gute Generics. Klar wird es gut versteckt, aber Hack bleibt Hack. Welche möglichkeit bieten mir Java Generics denn, die ich nicht mit geringem Aufwand auch ohne Generics hinbekomme?

    ein Concept Check geht ja simpel:
    (ConceptA)obj;
    Und sonst erspart es mir nur die Casts selber zu schreiben.
    Oder übersehe ich einen wesentlichen Punkt?

    In C# sind Generics Native. Da habe ich auch noch die Typinformationen zur Runtime - kann also auch Generics zur Laufzeit erstellen usw. Da hat man wirklich neue Möglichkeiten.

    Concepts sind aber nicht wirklich so neu - oder können Java Concepts etwas, dass ich nicht kenne? Concepts sind doch ein einfaches "Pattern Matching" ala "Typ X implementiert Interface A und erbt von Klasse B".
    Concepts in C++ sind da sogar noch etwas weiter - indem eben nicht nur Typen gecheckt werden können, sondern sogar einzelne Funktionen.

    Ok. Dann sind sie in Java so neu eben doch nicht. Das mit den Typinformationen ist leider schade, insofern bietet C# da tatsächlich eher was neues.
    Das mit dem "Concepts auf Methodenebene in C++" ist aber ein ziemlich schlechter Witz. Der C++ Compiler probiert richtig dumm aus, ob es geht oder nicht. Wie ein Spielkind.
    Ich kann auch für jede Methode ein Interface anbieten. Aber das ist natürlich nicht der Sinn der Sache und ich würde darin keinen Vorteil sehen. Das man in C++ keine Interfaces implementieren muss, kann eher noch ein zusätzliches Problem sein. C++ hat ja durchaus die Tendenz, ein bisschen mehrdeutig zu sein. Vielleicht meckert der Compiler gar nicht, weil er implizit mein Foo in ein Bar umwandeln kann (vielleicht hat er nen Konstruktor gefunden) und compiliert dann was zusammen, was ich nicht beabsichtigt habe.



  • Optimizer schrieb:

    So etwas wäre Selbstmord.

    Warum? Fliegt doch bloss eine BadCastException oder wie sie auch immer heissen mag.

    Es kann dir ja niemand garantieren, dass T Compareable ist.

    Wozu auch? Wenn jemand sort() verwenden will, muss T Comparable sein. Ist T das nicht, dann geht sort() nicht und man hat ohne auszukommen.

    Nein, so etwas würde man nicht machen, es ist nicht nützlich und dafür gibt es auch nie einen guten Grund. Es gibt ja nicht zum Spaß die Constraints und ich könnte die Anforderung an den Typ T stellen, dieses Interface zu implementieren.

    Wie würdest du mein imiginäres Problem mit Plugin und List lösen?

    Das ist kein Vergleich. Beim casten entlässt man immer den Compiler aus der Verantwortung.

    Das will ich ja. Ich will ja eben die Beschränkung umgehen.

    Ich betone es nochmal: So etwas würde man wie in dem Beispiel oben niemals machen. Es gibt nicht den geringsten Grund dafür.

    Warum?
    Ich würde es machen.

    Das hat mit default-Einstellung nichts zu tun. Innerhalb eines generischen Typs, wo ich alle Anforderungen, die ich haben will, definieren kann, ist casten vorsätzliche Sabotage. Jeder vernünftige Compiler warnt davor.

    Warum? Ich will ja eben _nicht_ alle Anforderungen festlegen - weil ich optionale Komponenten habe.

    Nein. Man würde eine Klasse List<T> schreiben und davon eine Klassen SortableList<T extends ICompareable> ableiten. Casten ist definitiv tabu. Das ist ja gerade der Witz. 🙂
    Wie ich jetzt z.B. auf Strings spezialisieren könnte, steht oben.

    Und was machen wir, wenn ich für .sort() IComparable brauche und für .clone() eine .clone() Methode? Habe ich dann
    List, SortableListe, CloneableList, SortableCloneableList?

    Ich will mich aber nicht auf ein Beispiel fixieren.

    Ja. Es kann mit Constraints etwas umständlicher sein. Ist mir auch einmal schon passiert. Constraints haben nicht nur Vorteile. Vollkommen klar. Ich will auch nur sagen, dass es ein anderes Konzept ist.

    Anders als was? Als in C++? Ne, das sehe ich nicht.

    Ich persönlich finde es schöner, du kannst natürlich völlig anderer Meinung sein. Allerdings ist es btw. nicht wirklich ein Aufwand, jetzt von der List<T> abzuleiten und noch eine sort-Methode dazuzudefinieren. Das muss man schon auch mal sehen.

    Ja, das ist ein Problem. Denn wie mache ich eine SortableClonableList?

    Ok. Dann sind sie in Java so neu eben doch nicht. Das mit den Typinformationen ist leider schade, insofern bietet C# da tatsächlich eher was neues.
    Das mit dem "Concepts auf Methodenebene in C++" ist aber ein ziemlich schlechter Witz. Der C++ Compiler probiert richtig dumm aus, ob es geht oder nicht. Wie ein Spielkind.

    Na und? Soll er probieren. In Java macht er es doch genauso. Er castet und schaut ob es gut geht. Oder er schaut direkt nach - ändert auch nicht viel. Natürlich ist 'nachschauen' schöner als 'ausprobieren' aber das Resultat ist das selbe. (Anders als bei der Implementierung von Generics in Java - die eben das selbe Resultat liefern wie wenn der User selber castet -> im Gegensatz zu C# wo das Resultat etwas anderes ist).

    Ich kann auch für jede Methode ein Interface anbieten.

    Jein, leider nicht so einfach.
    Denn eine Klasse muss das Interface implementieren. Man kann also nicht nachträglich ein Interface einfügen. Somit kann ich nicht ein eigenes Interface für einen Container schreiben - weil ich somit alle Objekte ändern müsste die ich je in den Container reingeben will. Das ist etwas doof.

    Das man in C++ keine Interfaces implementieren muss, kann eher noch ein zusätzliches Problem sein. C++ hat ja durchaus die Tendenz, ein bisschen mehrdeutig zu sein. Vielleicht meckert der Compiler gar nicht, weil er implizit mein Foo in ein Bar umwandeln kann (vielleicht hat er nen Konstruktor gefunden) und compiliert dann was zusammen, was ich nicht beabsichtigt habe.

    Das hat nichts mit Interfaces zu tun, sondern mit impliziter Typumwandlung. Einfach alle Ctors explicit machen und das Problem ist größtenteils behoben. Allerdings sehe ich den Zusammenhang mit impliziter Typumwandlung hier nicht...


Anmelden zum Antworten