Also schreiben wir:
Customer c = new Customer();
Warum ist das Design nicht so, dass wir schreiben:
c = new Customer();
c.CreditLimit = 1000;
Der Compiler kann c Punkte für einen Kunden berechnen und es ermöglichen, dass Mitglieder des Kunden auf c?
Ich weiß, wir möchten vielleicht schreiben:
IPerson c = new Customer();
IPerson e = new Employee();
um schreiben zu können:
public string GetName(IPerson object)
{
return object.Name
}
string name = GetName(c); // or GetName(e);
Aber wenn wir geschrieben haben:
c = new Customer();
e = new Employee();
wir konnten noch schreiben:
public string GetName(object)
{
return object.Name
}
string name = GetName(c); // or GetName(e);
Der Compiler könnte sich über den Code direkt darüber beschweren, wenn der Typ der Objekt-c-Referenzen keine Name-Eigenschaft unterstützt (da er überprüfen kann, welche Mitglieder für das Argument / den Parameter innerhalb der Methode verwendet werden), oder die Laufzeit könnte sich beschweren.
Selbst mit dem dynamischen Schlüsselwort von C # verwenden wir immer noch eine Variable 'type' (zur Laufzeit festgelegt). Aber warum braucht eine Variable überhaupt einen Typ? Ich bin mir sicher, dass es einen guten Grund geben muss, aber ich kann mir das nicht vorstellen!
var
in C # verwenden, und es ist immer gut, genau zu sagen, wo Sie eine Variable deklarieren möchten.Antworten:
quelle
a = new Bar()
eine Methode aus der Klasse ausführen und später aufrufenBaz
), gibt der Compiler einen Fehler aus. Sprachen wie Haskell und OCaml waren Pioniere der Typinferenz, aber sie sind in C # mit demvar
Schlüsselwort vorhanden.Sie haben einen vollkommen gültigen Punkt, es gibt Sprachen, die den Typ einer Variablen nicht verfolgen, und sie werden als "dynamisch typisiert" bezeichnet. Die Kategorie umfasst Sprachen wie JavaScript, Perl, Lisp und Python.
Der Vorteil einer statisch typisierten Sprache ist eine zusätzliche Fehlerprüfung zur Kompilierungszeit.
Angenommen, Sie haben die folgende Methode:
Wenn Sie einen Kunden
bob
und einen Mitarbeiterjames
in Ihrem Code haben, können Sie versehentlich anrufenaddCustomerContact(james, bob)
, was ungültig ist. Wenn der Compiler die Variablentypen nicht kennt, kann er Sie nicht warnen, dass Sie einen ungültigen Aufruf getätigt haben. Stattdessen tritt zur Laufzeit ein Fehler auf ... und da dynamisch typisierte Sprachen dies nicht überprüfen Typ von Parametern, die an Methoden übergeben werden. Dieses Problem tritt immer dann auf, wenn Ihr Code versucht, Nur-Kunden-Eigenschaften desjames
Objekts oder Nur-Mitarbeiter-Eigenschaften desbob
Objekts zu verwenden. Das kann lange dauern, nachdem das Paar (James, Bob) zur Liste der Kundenkontakte hinzugefügt wurde.Nun fragen Sie sich vielleicht, warum der Compiler den Typ von
james
und nicht immer noch ableitenbob
und uns trotzdem warnen kann. Das mag manchmal möglich sein, aber wenn Variablen wirklich keinen Typ haben, könnten wir Folgendes tun:Es ist völlig legal, einer Variablen einen Wert zuzuweisen, da wir sagten, dass Variablen keinen Typ haben. Das bedeutet auch, dass wir den Typ einer Variablen nicht immer kennen können, da es sich um unterschiedliche Typen handeln kann, die auf unterschiedlichen Ausführungspfaden basieren.
Im Allgemeinen werden dynamisch typisierte Sprachen für Skriptsprachen verwendet, in denen kein Kompilierungsschritt vorhanden ist und daher keine Kompilierungsfehler vorhanden sind. Dies bedeutet, dass die zusätzlichen Tastenanschläge, die zum Geben des Variablentyps erforderlich sind, nicht sehr nützlich sind.
Dynamisch typisierte Sprachen bieten auch einige deutliche Vorteile, vor allem, weil weniger Code für die Implementierung desselben Designs benötigt wird: Schnittstellen müssen nicht geschrieben werden, da alles "ententypisiert" ist (es ist uns nur wichtig, welche Methoden / Eigenschaften ein Objekt hat (nicht zu welcher Klasse das Objekt gehört), Variablen müssen keinen expliziten Typ erhalten ... mit dem Kompromiss, dass wir etwas weniger Fehler herausfinden, bevor wir unseren Code ausführen.
quelle
Professionelle Programmierer müssen also nicht herausfinden, ob
Was es ein Fehler ist, zur Kompilierungszeit mit einer statisch typisierten Sprache oder zur Laufzeit mit einer dynamisch typisierten Sprache. Na ja, vernünftige sowieso.
quelle
Angenommen, Sie hatten eine Variable
one
(auf 1 gesetzt) und haben versucht, sie auszuwertenone + one
. Wenn Sie keine Ahnung vom Typ hatten, ist 1 + 1 nicht eindeutig. Sie können argumentieren, dass 2 oder 11 richtige Antworten sein könnten. Es wird mehrdeutig, wenn der Kontext nicht angegeben wird.Ich habe gesehen, dass dies in SQLite passiert ist, wo die Datenbanktypen versehentlich auf gesetzt wurden,
VARCHAR
anstattINT
und wenn Operationen ausgeführt wurden, erhielten die Leute unerwartete Ergebnisse.Wenn der Kontext in c # auf einen Typ folgt, können Sie das
var
Schlüsselwort verwenden.Kompiliert c und e mit den abgeleiteten Typen zur Kompilierungszeit.
quelle
1 + 1
immer den Typint
, aber das muss nicht deklariert werden. Die Frage ist, warum Variablen einen Typ haben, keine Werte .variables
nicht sehen,values
wann ich1 + 1
in meinem Beispiel verwendet habe. Ich denke es war nicht klar.one=1; print(one+one)
druckt2
.one="1"; print(one+one)
druckt11
. Das SQLite-Beispiel ist überzeugender, aber das Problem besteht in einer schwachen Typisierung, sodass es für C # nicht wirklich relevant ist.ORDER BY
versehentlich auf einemVARCHAR
Feld gemacht gesehen. Siehe stackoverflow.com/questions/9103313/… .Einer Variablen muss kein Typ zugeordnet sein. Zu den Sprachen, in denen dies zutrifft, gehören Lisp, Scheme, Erlang, Prolog, Smalltalk, Perl, Python, Ruby und andere.
Es ist auch möglich , eine Variable hat einen Typen, aber Sie könnten nicht haben zu schreiben , die Art im Programm. Dies wird normalerweise als Typinferenz bezeichnet. ML, Haskell und ihre Nachkommen haben eine starke Typinferenz; Einige andere Sprachen haben es in kleineren Formen, wie zum Beispiel die
auto
Deklarationen von C ++ .Das Hauptargument gegen Typinferenz ist, dass es die Lesbarkeit beeinträchtigt. Es ist normalerweise einfacher, Code zu verstehen, wenn die Typen aufgeschrieben werden.
quelle
Wenn Sie den Typ identifizieren, den Ihre Variable darstellt, geben Sie eine Erklärung zu einigen Dingen ab. Sie identifizieren die Speicherzuordnungsanforderungen für Ihre Variable und definieren Kompatibilitäts- und Bereichsregeln für Ihre Variable. Dies bietet eine Möglichkeit, Verwirrung über Ihre Absichten für die von Ihnen gespeicherten Daten zu vermeiden und Ihnen ein relativ billiges Mittel zur Verfügung zu stellen, um potenzielle Probleme in Ihrem Code beim Kompilieren zu identifizieren.
Wenn Sie folgende Variablen deklarieren:
Was können Sie über diese Variablen schließen? Ist
myVar
signiert oder nicht signiert? Ist es 8-Bit, 64-Bit oder etwas dazwischen? IstmyOtherVar
ein String (effektiv ein Array) oder ein Char? Ist es ANSI oder Unicode?Durch die Angabe bestimmter Datentypen geben Sie dem Compiler Hinweise, wie er die Speicheranforderungen für Ihre Anwendung optimieren kann. Einige Sprachen stören sich nicht allzu sehr an solchen Dingen, sodass diese Angelegenheiten zur Laufzeit behandelt werden können, während andere Sprachen eine gewisse dynamische Typisierung zulassen, da durch die Analyse des Codes auf die Datentypen geschlossen werden kann.
Ein weiterer Punkt bei stark typisierten Sprachen ist, dass Sie dem Compiler nicht jedes Mal Anweisungen geben müssen, wenn Sie eine Variable verwenden. Können Sie sich vorstellen, wie schrecklich und unlesbar Ihr Code werden würde, wenn Sie jedes Mal, wenn Sie auf eine Variable zugreifen, gezwungen wären, sie effektiv umzuwandeln, um dem Compiler mitzuteilen, um welche Art von Wert es sich handelt? !!
quelle
Ein Computerprogramm ist ein Diagramm von Prozessknoten, das beschreibt, was eine "Maschine", dargestellt durch die Sprachlaufzeit (in den meisten Fällen um Toolkits erweitert), in welcher Reihenfolge oder unter welchen Bedingungen tun sollte. Dieses Diagramm wird durch eine Textdatei (oder eine Reihe von Textdateien) dargestellt, die in einer bestimmten Sprache geschrieben und (teilweise oder vollständig) erstellt wird, wenn der Compiler / Interpreter diese Datei liest (deserialisiert). Es gibt auch einige Umgebungen (UML- oder grafische Programmgenerierungswerkzeuge), in denen Sie dieses Diagramm tatsächlich erstellen und den Quellcode in einer Zielsprache generieren können.
Warum sage ich das? Weil dies zur Antwort auf Ihre Frage führt.
Ihr Programmtext enthält Anweisungen, wie der Computer die eigentliche Aufgabe lösen soll. Er enthält sowohl die Prozessschritte (Bedingungen, Aktionen) als auch die Struktur (welche Komponenten verwenden Sie in der Lösung). Letzteres bedeutet, dass Sie einige Instanzen anderer Komponenten abrufen oder erstellen, sie in benannte Felder (Variablen) einfügen und sie verwenden: Zugriff auf ihre Daten und Dienste.
In einigen Sprachen erhalten Sie einheitliche Kästchen, in denen nur die Beschriftung wichtig ist. Sie können jedoch alles in sie einfügen. Sie können sogar eine Variable mit dem Namen "Ziel" verwenden, um eine "Person" am Anfang und "Auto" am Ende von zu speichern der gleiche Algorithmus. Bei anderen müssen Sie "geformte" Boxen erstellen, daher unterschiedliche für eine Person oder ein Auto - obwohl Sie damit immer noch eine "generische Box" erstellen können (Java Object, C / C ++ void *, Objective C "id" ...) und wirf es wie du willst. Mit typisierten Sprachen können Sie Ihre Struktur in feineren Details ausdrücken und "Typverträge" für Ihre Variablen erstellen (obwohl Sie diese Einschränkung umgehen können), während untypisierte Sprachen diesen Ansatz "Ich werde sicher wissen, was ich dieses Mal in diese Box gesteckt habe" unterstützen als Standard und einziges Verhalten.
Beide Ansätze sind praktikabel, haben ihre Compiler-Intelligenz, viele Programmierbücher, Praktiken und Frameworks, die mit ihnen (und anderen Tonnen von Büchern über diese Frameworks) auf verschiedenen Ebenen geschrieben wurden. Daher scheint die Antwort heute eher eine Frage des Geschmacks und des Wissens des tatsächlichen Programmiererteams zu sein als eine richtig begründete, gemessene und überprüfte Aussage darüber, ob Typen verwendet werden sollen oder nicht.
Ich denke, es ist unnötig zu erwähnen, dass ich Regeln Tricks vorziehe, insbesondere bei langfristigen Projekten mit großen Teams (auch bekannt als "ernst"). Grund: Soweit ich weiß, sind die wahrscheinlichsten Ursachen für ein Versagen / Ausrutschen eines SW-Projekts: unklare Anforderungen und schlechtes Design (80%! Nach einer mir bekannten Studie), und nur wenige Prozent bleiben für die tatsächliche Codierung übrig. Alle Regeln und Verträge erzwingen ein saubereres Design, denken voraus und erfordern, dass die Entscheidungen früher und von den richtigen Personen getroffen werden. Typen bedeuten Regeln: weniger "Freiheit" und "Coolness" - mehr Vorbereitung, Denken, Kodierungsstandards, kontrollierte Teamarbeit. Für mich klingt dies nach einem erforderlichen Erfolgsfaktor und auch nach "Zuhause, süßes Zuhause".
Meine 2 Cent.
quelle
AFIAK Alle Sprachen mit dynamischer Typisierung sind interpretierte Sprachen. Das ist bereits sehr ineffizient. Das Hinzufügen der Ineffizienz des dynamischen Tippens wird keinen großen Zeitverlust bedeuten. Eine kompilierte Sprache bezieht sich jedoch nicht auf Dinge mit Namen, wenn sie ausgeführt wird. (Abgesehen von der gelegentlichen Verwendung von .net-Reflektion oder Ähnlichem - Funktionen, die im Vergleich zur zugrunde liegenden Sprache sehr langsam sind.) Die Suche nach all diesen Namen wird langsam, langsam, langsam sein.
quelle
Dynamisch typisierte Sprachen werden oft als "objektorientiert" angepriesen. Sie sind nicht. Sie können einkapselungsorientiert sein, aber niemals objektorientiert. Bei der Objektorientierung dreht sich alles um Typen.
"Der Junge fährt mit dem Fahrrad seines Bruders zum Lebensmittelgeschäft und kauft dem Lebensmittelhändler einen Laib Brot." Mithilfe der Objektorientierung kann sofort eine Reihe von Klassen (Typen) geschrieben werden, um dieses reale Szenario zu beschreiben.
In einer dynamisch typisierten Sprache konnte das Szenario nur so dargestellt werden:
"Das Objekt reitet das Objekt seines Objekts zum Objekt und kauft ein Objekt vom Objekt".
Die Kraft der Objektorientierung liegt in ihrer Fähigkeit, die Welt auf natürliche Weise zu modellieren, so dass der Softwareentwickler beide Seiten des Gehirns verwenden kann, um Software zu schreiben und Probleme mehr als Mensch, weniger als Computerprogrammierer zu lösen. Diese Kraft fehlt in dynamisch typisierten Sprachen.
Die statische Typisierung ermöglicht eine bessere Codierungseffizienz, Wiederverwendbarkeit und Wartbarkeit, da integrierte Entwicklungsumgebungen die Variablentypen kennen. Wenn eine IDE die Variablentypen kennt, kann sie eine automatische Vervollständigung bereitstellen, sodass der Programmierer nicht auf die Klassendefinition zurückgreifen muss, um sich zu merken, ob die Member-Eigenschaft "backlightControl" oder "backLightControl" oder "bkLightCtrl" geschrieben wurde.
Die statische Typisierung ermöglicht ein automatisiertes Refactoring, da die IDE jeden Ort kennt, an dem eine Variable eine Instanz des zu refactoringenden Objekts enthält.
Die statische Typisierung ermöglicht eine bessere Wiederverwendbarkeit und Wartbarkeit. Dynamische Eingabe ist besser für Einwegcode. Angenommen, ein neuer Entwickler kommt von der Straße und sieht sich einen vorhandenen Code an. Wenn der Code statisch typisiert ist, kann der Entwickler mit zwei Mausklicks die Klassendefinition jeder der beteiligten Variablen überprüfen, weiß, wofür die Klasse ist, weiß, welche anderen Methoden und Eigenschaften verfügbar sind. Wenn der Code dynamisch eingegeben wird, muss der Entwickler die globale Suche verwenden, um herauszufinden, was los ist.
quelle
Boy
Klasse, aber ich bezweifle, dass sie alles kann, was ein "Junge" aus der realen Welt tut. In Ihrem dynamischen Beispiel (Das Objekt fährt ...) wissen wir jedoch das einzig Wichtige an diesem "Jungen" -Objekt - es kann fahren . Das ist die Grundphilosophie dynamischer Sprachen. Es hat + ve s und -ve s. Welches du magst, ist deine Meinung.