Umfasst die Java-Entwicklung normalerweise mehr Unterklassen als C # /. NET?

34

Ich habe vor kurzem angefangen, mich mit Android-Entwicklung zu beschäftigen. Dies hat mich zurück in die Welt der Java-Softwareentwicklung geführt. Das letzte Mal, als ich mit Java gearbeitet habe, habe ich OOP zugegebenermaßen nicht annähernd so gut verstanden wie jetzt (glaube ich).

Nachdem ich in meiner Karriere hauptsächlich C # verwendet habe, bemerke ich einen verblüffenden Unterschied in der Verwendung von Java und C # bei der Vererbung.

In C # schien die Vererbung in den meisten Situationen vermieden werden zu können. Die vorliegende Aufgabe kann normalerweise mithilfe konkreter Klassen des .NET- Frameworks ausgeführt werden.

In Java sieht es so aus, als ob das Java-Framework viele Schnittstellen oder abstrakte Klassen enthält, die vom Entwickler implementiert / erweitert werden sollen.

Dies scheint ein zu großer Unterschied zu sein, als dass man sich auf den Stil beschränken könnte. Was ist die Begründung dafür? Ich habe das Gefühl, dass ich keinen sauberen Java-Code schreiben werde, bis ich das verstanden habe.

Beschränkt sich dies nur auf das Android SDK oder handelt es sich um einen Java-weiten Ansatz für OOP?

Oder anders ausgedrückt:

Was ist mit dem Design dieser beiden Sprachen, das (anscheinend) mehr oder weniger Vererbung fördert als die andere?

Wenn die Sprachen die Vererbung identisch behandeln und vorausgesetzt, dass meine Beobachtung gültig ist, dann bedeutet dies, dass dies mit dem Design der Frameworks / Bibliotheken zusammenhängt und nicht mit den Sprachen. Was wäre die Motivation für diese Art von Design?

MetaFight
quelle
1
Es ist wahr. Java hat viel zu viele Schnittstellen. Ich würde gerne wissen, warum dieses Entwicklerverhalten für eine bestimmte Sprache üblich ist. Ich sehe, dass dies in Java-Projekten häufiger vorkommt als in allen anderen. Es muss einen Grund dafür geben und nicht nur eine Meinung.
Reactgular
1
@MathewFoscarini es ist nur deine Meinung . In Java-Projekten, an denen ich beteiligt war, neigten die Entwickler dazu, Vererbung wie eine Seuche zu vermeiden. Nichts Maßgebendes hier, nur meine Meinung . Willst du wählen ?
gnat
2
In Java müssen Sie fast nie eine Klasse von einer anderen ableiten. Stattdessen können Sie Schnittstellen implementieren, um Polymorphismus zu erzielen, und zusammengesetzte Objekte implementieren und die Methode als Proxy aufrufen, um eine shaired-Funktionalität zu erzielen.
DwB
1
@ThinkingMedia Im Allgemeinen wird Java von OSS-Eiferern / Puristen überflutet. Akademische Grundsätze sind das vorrangige Anliegen. .Net-Entwickler sind Pragmatiker, denen es darum geht, die Arbeit zu erledigen. Sie schätzen den Arbeitscode mehr als den saubersten Code.
Andy

Antworten:

31

Dies scheint ein zu großer Unterschied zu sein, als dass man sich auf den Stil beschränken könnte. Was ist die Begründung dafür?

Mein Verständnis ist , dass es im Wesentlichen ist einfach eine stilistische Entscheidung. Na ja, vielleicht nicht Stil, sondern die Redewendungen der Sprache / Umgebung. Entwickler von Java-Standardbibliotheken befolgten eine Reihe von Designrichtlinien und die .NET-Entwickler eine andere (obwohl sie die Möglichkeit hatten, zu sehen, wie Javas Ansatz funktionierte).

In den eigentlichen Sprachen gibt es sehr wenig, um die Vererbung zu fördern oder abzubringen. Nur zwei Dinge erscheinen mir relevant:

  1. .NET führte Generika früher in ihrem Leben ein, bevor zu viel nicht generischer Code implementiert wurde. Die Alternative ist viel Vererbung, um Dinge zu spezialisieren.

  2. Eine größere Änderung war, dass .NET Delegaten unterstützt. In Java stecken Sie in der (anonymen) Vererbung, um die grundlegendste Variablenfunktionalität bereitzustellen. Dies führt zu einem relativ großen Unterschied in der Art und Weise, wie Code entwickelt wurde, um entweder die Vorteile von Delegaten zu nutzen oder um die umständlichen Vererbungsstrukturen zu vermeiden, die für die Ausführung in Java erforderlich sind.

Telastyn
quelle
3
Ich denke, diese Antwort bietet eine sehr plausible Erklärung. Besonders der Punkt über anonyme Vererbung anstelle von Delegierten. Ich habe das viel beobachtet. Vielen Dank.
MetaFight
3
Vergessen Sie nicht die in .NET 3.5 eingeführten anonymen Typen und Lambda-Syntax- / Ausdrucksbäume. Und natürlich können Sie die dynamische Typisierung in .NET 4 aktivieren. Es handelt sich derzeit zweifellos um eine gemischte Paradigmasprache, die nicht streng objektorientiert ist.
Aaronaught
Ja, nach meiner Erfahrung, die beide verwendet hat (auch in gemischten Projekten, in denen die gleichen Leute beide Sprachen verwenden), bevorzugen die Leute beim Codieren von Java eine größere Anzahl kleinerer Klassen, bei der Codierung eine kleinere Anzahl größerer Klassen (Tendenz zu Gottklassen) mit C #. Wenn Sie absichtlich dasselbe Ding mit demselben Stil in beiden Prototypen erstellen, erhalten Sie eine ähnliche Anzahl von Klassen (bei Verwendung von Teilklassen erhalten Sie wahrscheinlich mehr Codedateien, selbst wenn Sie C # verwenden).
Jwenting
6

Dies sind sehr unterschiedliche Sprachen, insbesondere in diesem Bereich. Nehmen wir an, Sie haben eine Klasse. In diesem Fall machen wir daraus ein Benutzersteuerelement, so etwas wie ein Textfeld. Nennen Sie es UIControl. Jetzt wollen wir das in eine andere Klasse einordnen. Da wir in diesem Fall eine Benutzeroberfläche für unser Beispiel verwenden, nennen wir sie die CleverPanel-Klasse. Unsere CleverPanel-Instanz möchte aus verschiedenen Gründen wissen, was mit ihrer UIControl-Instanz passiert. Wie macht man das?

In C # besteht der grundlegende Ansatz darin, nach verschiedenen Ereignissen zu suchen und Methoden einzurichten, die ausgeführt werden, wenn jedes interessante Ereignis ausgelöst wird. In Java, in dem es an Ereignissen mangelt, besteht die übliche Lösung darin, ein Objekt mit verschiedenen "Ereignis" -Behandlungsmethoden an eine UIControl-Methode zu übergeben:

boolean  stillNeedIt =  ... ;
uiControl.whenSomethingHappens( new DoSomething()  {
    public void resized( Rectangle r )  { ... }
    public boolean canICloseNow()  { return !stillNeedIt; }
    public void closed()  { ... }
    ...
} );

Bisher ist der Unterschied zwischen C # und Java nicht tiefgreifend. Wir haben jedoch die DoSomething-Schnittstelle, die in C # nicht benötigt wird. Außerdem enthält diese Schnittstelle möglicherweise viele Methoden, die die meiste Zeit nicht benötigt werden. In C # behandeln wir dieses Ereignis einfach nicht. In Java erstellen wir eine Klasse, die eine Null-Implementierung für alle Schnittstellenmethoden bereitstellt, DoSomethingAdapter. Jetzt ersetzen wir DoSomething durch DoSomethingAdapter und müssen für eine saubere Kompilierung überhaupt keine Methoden schreiben. Am Ende überschreiben wir nur die Methoden, die wir benötigen, damit das Programm richtig funktioniert. Daher benötigen wir eine Schnittstelle und verwenden Vererbung in Java, um das, was wir getan haben, mit Ereignissen in C # abzugleichen.

Dies ist ein Beispiel, keine umfassende Erörterung, aber es enthält die Grundlagen, warum Java im Gegensatz zu C # so viel vererbt.

Warum funktioniert Java so? Flexibilität. Das Objekt wurde übergeben, wenn Something Happens vollständig an CleverPanel übergeben werden konnte. Möglicherweise sollten mehrere CleverPanel-Instanzen an ihre UIControl-ähnlichen Objekte übergeben werden, um irgendwo ein CleverWindow-Objekt zu unterstützen. Oder die UIControl könnte es an eine ihrer Komponenten übergeben.

Anstelle eines Adapters kann es auch eine DoSomething-Implementierung geben, die Tausende von Codezeilen enthält. Wir könnten eine neue Instanz erstellen , dass es passieren. Möglicherweise müssen wir eine Methode überschreiben. Ein häufiger Trick in Java ist, eine große Klasse mit einer Methode wie der folgenden zu haben:

public class BigClass implements DoSomething  {
    ...many long methods...
    protected int getDiameter()  { return 5; }
}

Dann in CleverlPanel:

uiControl.whenSomethingHappens( new BigClass()  {
    @Override
    public int getDiameter()  { return UIPanel.currentDiameter; }
} );

Die Open-Source-Java-Plattform leistet einen großen Beitrag dazu, dass Programmierer mehr tun - sowohl, weil sie dem Beispiel folgen als auch einfach, um es zu nutzen. Ich denke, dass das grundlegende Design der Sprache hinter dem Framework-Design von Sun und hinter dem Einsatz der Techniken durch Java-Programmierer steckt, wenn das Framework nicht verwendet wird.

In Java ist es ganz einfach, eine Klasse im laufenden Betrieb zu erstellen. Die Klasse, anonym oder benannt, muss nur in einem kleinen Codeblock referenziert werden, der tief in einer Methode vergraben ist. Es kann komplett neu erstellt werden oder durch geringfügige Änderungen an einer sehr großen, vorhandenen Klasse. (Und die vorhandene Klasse kann sich auf oberster Ebene in ihrer eigenen Datei befinden oder in einer Klasse auf oberster Ebene verschachtelt sein oder nur innerhalb eines einzelnen Codeblocks definiert sein.) Die neue Klasseninstanz kann vollen Zugriff auf alle Daten des erstellenden Objekts haben. Die neue Instanz kann im gesamten Programm übergeben und verwendet werden und stellt das Objekt dar, von dem sie erstellt wurde.

(Beachten Sie außerdem, dass die Vererbung in großem Umfang hier - wie auch an anderen Stellen in Java - nur zu DRY-Zwecken verwendet wird. Verschiedene Klassen können denselben Code wiederverwenden. Beachten Sie auch die einfache Vererbung in Java, die dies fördert. )

Auch dies ist keine umfassende Diskussion. Ich kratz hier nur an der Oberfläche. Aber ja, es gibt einen verblüffenden Unterschied in der Verwendung der Vererbung zwischen Java und C #. Sie sind in dieser Hinsicht sehr unterschiedliche Sprachen. Es ist nicht deine Einbildung.

RalphChapin
quelle
Hinweis: Sie können die Bereitstellung von Methoden vermeiden, indem Sie eine abstrakte Klasse mit leeren Implementierungen erweitern. Auf diese Weise können Sie die Methoden, die etwas bewirken, selektiv überschreiben. Obwohl es nicht so hässlich ist, bedeutet es eine andere Vererbungsebene.
Peter Lawrey
-2

Es gibt absolut keinen Unterschied in der Art und Weise, wie die Vererbung zwischen Java und C # behandelt wird. Wann Sie tatsächlich Vererbung oder Komposition verwenden, ist definitiv eine Entwurfsentscheidung und keinesfalls etwas, das Java oder C # ermutigen oder entmutigen. Ich empfehle Ihnen, diesen Artikel zu lesen .

Hoffe ich habe geholfen!

Pantelis Natsiavas
quelle
5
Sie sprechen über die Sprachen selbst, aber ich denke, die Frage betrifft auch die Bibliotheken und die allgemeine Verwendung.
Svick
3
In der restlichen Sprache gibt es jedoch einige Besonderheiten, die eine zusätzliche Vererbung in Java fördern. siehe RalphChapins Antwort
Izkata