Ich habe C # in den letzten sechs Monaten oder so gelernt und beschäftige mich jetzt mit Java. Meine Frage bezieht sich auf die Instanzerstellung (in beiden Sprachen) und mehr auf: Ich frage mich, warum sie das so gemacht haben. Nehmen Sie dieses Beispiel
Person Bob = new Person();
Gibt es einen Grund, warum das Objekt zweimal angegeben wird? Würde es jemals eine geben something_else Bob = new Person()
?
Es würde scheinen, wenn ich mich an die Konvention halten würde, wäre es eher so:
int XIsAnInt;
Person BobIsAPerson;
Oder vielleicht einer von diesen:
Person() Bob;
new Person Bob;
new Person() Bob;
Bob = new Person();
Ich denke, ich bin neugierig, ob es eine bessere Antwort gibt als "so wird es gemacht".
java
c#
object-oriented
Jason Wohlgemuth
quelle
quelle
LivingThing
? Du könntest schreibenLivingThing lt = new Person()
. Suchen Sie nach Vererbung und Schnittstellen.Person Bob
deklariert eine Variable vom Typ "reference toPerson
", die aufgerufen wirdBob
.new Person()
Erstellt einPerson
Objekt. Referenzen, Variablen und Objekte sind drei verschiedene Dinge!var bob = new Person();
?Person Bob();
ist in C ++ möglich und bedeutet fast dasselbe wiePerson Bob = Person();
Antworten:
Ja, wegen der Vererbung. Wenn:
Dann:
Bob ist auch eine Person und will nicht anders behandelt werden als jeder andere.
Außerdem könnten wir Bob mit Superkräften ausstatten:
Und so wird er es nicht ertragen, anders behandelt zu werden als jeder andere Moderator. Und er schleicht gerne im Forum herum, um alle in der Reihe zu halten, während er inkognito ist:
Wenn er dann ein schlechtes erstes Poster findet, wirft er seinen Umhang der Unsichtbarkeit ab und stürzt sich.
Und danach kann er alles Unschuldige und so weiter tun:
quelle
enum
.Lassen Sie uns Ihre erste Codezeile nehmen und untersuchen.
Die erste
Person
ist eine Typspezifikation. In C # können wir darauf verzichten, indem wir einfach sagenund der Compiler ableiten , die Art des Variablen Bob vom Konstruktoraufruf
Person()
.Aber vielleicht möchten Sie so etwas schreiben:
Wenn Sie nicht den gesamten API-Vertrag von Person erfüllen, sondern nur den von der Schnittstelle angegebenen Vertrag
IPerson
.quelle
IPerson
Beispiel in meinem Code ausführen, um sicherzustellen, dass ich nicht versehentlich private Methoden verwende, wenn ich Code schreibe, der in eine andereIPerson
Implementierung kopiert / eingefügt werden soll.internal
?private
es Sinn macht: Factory-Methoden, die Teil der Klasse sind, die instanziiert wird. In meiner Situation sollte der Zugang zu privaten Werten die Ausnahme sein, nicht die Norm. Ich arbeite an Code, der mich noch lange überleben wird. Wenn ich das so mache, ist es nicht nur unwahrscheinlich, dass ich private Methoden selbst verwende, sondern wenn der nächste Entwickler diese ein paar Dutzend Stellen kopiert / einfügt und der Entwickler sie danach kopiert, verringert sich die Wahrscheinlichkeit, dass jemand eine Gelegenheit dazu sieht Verwenden Sie private Methoden als "normales" Verhalten.Diese Syntax ist so ziemlich ein Erbe von C ++, das im Übrigen beides enthält:
und
Der erste, um ein Objekt innerhalb des aktuellen Bereichs zu erstellen, der zweite, um einen Zeiger auf ein dynamisches Objekt zu erstellen.
Das kannst du auf jeden Fall haben
something_else Bob = new Person()
Sie machen hier zwei verschiedene Dinge, geben den Typ der lokalen Variablen an
nums
und sagen, Sie möchten ein neues Objekt vom Typ 'Liste' erstellen und dort ablegen.C # stimmt mit Ihnen überein, da der Typ der Variablen die meiste Zeit mit dem übereinstimmt, was Sie in die Variable eingegeben haben:
In einigen Sprachen tun Sie Ihr Bestes, um die Angabe der Variablentypen wie in F # zu vermeiden :
quelle
new std::pair<int, char>()
, haben die Mitgliederfirst
undsecond
das Paar eine automatische Speicherdauer, aber sie werden wahrscheinlich auf dem Heap zugeordnet (als Mitglieder despair
Objekts für die dynamische Speicherdauer ).Es gibt einen großen Unterschied zwischen
int x
undPerson bob
. Einint
ist einint
ist einint
und es muss immer ein seinint
und kann nie etwas anderes als ein seinint
. Auch wenn Sie dasint
beim Deklarieren (int x;
) nicht initialisieren , wird es dennochint
auf den Standardwert gesetzt.Wenn Sie jedoch deklarieren
Person bob
, gibt es eine große Flexibilität, worauf sich der Namebob
zu einem bestimmten Zeitpunkt tatsächlich beziehen kann. Es könnte sich auf eine beziehenPerson
, oder es könnte sich auf eine andere Klasse beziehen, zBProgrammer
abgeleitet vonPerson
; es könnte sogar seinnull
, sich überhaupt auf kein Objekt zu beziehen.Beispielsweise:
Die Sprachdesigner hätten sicherlich eine alternative Syntax entwickeln können, die das Gleiche bewirkt hätte wie
Person carol = new Person()
bei weniger Symbolen, aber sie hätten es dennoch zulassen müssenPerson carol = new Person()
(oder eine seltsame Regel festlegen müssen, die dieses bestimmte der vier obigen Beispiele als illegal erklärt). Es ging ihnen mehr darum, die Sprache "einfach" zu halten, als extrem präzisen Code zu schreiben. Das mag ihre Entscheidung beeinflusst haben, die kürzere alternative Syntax nicht bereitzustellen, aber es war auf jeden Fall nicht notwendig und sie haben es nicht bereitgestellt.quelle
Die beiden Deklarationen können unterschiedlich sein, sind jedoch häufig gleich. Ein allgemein empfohlenes Muster in Java sieht folgendermaßen aus:
Diese Variablen
list
undmap
werden mithilfe der Schnittstellen deklariert,List
undMap
während der Code bestimmte Implementierungen instanziiert. Auf diese Weise hängt der Rest des Codes nur von den Schnittstellen ab, und es ist einfach, verschiedene Implementierungsklassen für die Instanziierung auszuwählenTreeMap
, da der Rest des Codes nicht von einem Teil derHashMap
API abhängen kann , der sich außerhalb derMap
Schnittstelle befindet.Ein weiteres Beispiel, bei dem sich die beiden Typen unterscheiden, ist eine Factory-Methode, die eine bestimmte Unterklasse zum Instanziieren auswählt und sie dann als Basistyp zurückgibt, sodass der Aufrufer die Implementierungsdetails nicht kennen muss, z.
Typinferenz kann die Quellcode-Redundanz beheben. ZB in Java
wird dank der Typinferenz und der Deklaration die richtige Art von Liste erstellen
In einigen Sprachen geht die Typinferenz weiter, z. B. in C ++
quelle
bob
, nichtBob
. Dies vermeidet viele Mehrdeutigkeiten, zB package.Class vs. Class.variable.clazz
.clazz
wird verwendet, daclass
es sich um ein Schlüsselwort handelt, sodass es nicht als Bezeichner verwendet werden kann.Class
ist eine vollkommen gültige Kennung.cLaSs
,cLASS
undcLASs
.Mit den Worten des Laien:
var = new Process()
Sie einfach nicht zuerst die Variable deklarieren.quelle
Es geht auch um die Kontrolle darüber, was passiert. Wenn die Deklaration eines Objekts / einer Variablen automatisch einen Konstruktor aufruft, z. B. if
war automatisch das gleiche wie
Dann könnten Sie (zum Beispiel) niemals statische Factory-Methoden verwenden, um Objekte zu instanziieren, anstatt Standardkonstruktoren zu verwenden. Das heißt, es gibt Zeiten, in denen Sie keinen Konstruktor für eine neue Objektinstanz aufrufen möchten.
Dieses Beispiel ist in erklärt Joshua Bloch ‚s Effective Java (Punkt 1 ironisch genug!)
quelle