Typprüfungen
Kurz gesagt: Eine Typprüfung mit instanceof fragt, ob ein Objekt zu einer bestimmten Klasse oder einer ihrer Unterklassen gehört, und typeof sagt, welche Art von einfachem Wert es ist.
Problem
Nur manche können laden
Eine Firma hat einen Fuhrpark aus normalen und elektrischen Autos. Jeden Abend müssen die elektrischen geladen werden. ElectricCar erbt von Car und fügt charge() hinzu, also stehen alle in einem Array:
const fleet = [ new Car("Skoda"), new ElectricCar("Tesla", 35), new Car("Dacia"), new ElectricCar("Nissan", 60),];for (const c of fleet) { c.charge();}Das Programm startet und bricht schon beim ersten Auto ab, „Skoda“: TypeError: c.charge is not a function. Bis zu den elektrischen kommt es nie.
Ein normales Auto lässt sich wirklich nicht laden. Du musst jedes Auto fragen: „Bist du elektrisch?“
Die Idee
Frag das Objekt, was es ist
for (const c of fleet) { if (c instanceof ElectricCar) { c.charge(); console.log(`${c.brand}: geladen auf ${c.battery}%`); }}Tesla: geladen auf 100%Nissan: geladen auf 100%c instanceof ElectricCar fragt das Objekt, auf das c zeigt: „Bist du ein ElectricCar?“ und gibt true oder false. Das nennt man Typprüfung.
Eine neue Variable brauchst du nicht. In JavaScript haben Variablen keinen Typ, also gibt es nichts umzuwandeln: Sobald die Prüfung wahr ist, zeigt c auf ein Elektroauto, und c.charge() funktioniert. Die Autos bleiben dieselben.
for (const c of fleet) { if (c instanceof ElectricCar) { c.charge(); console.log(`${c.brand}: geladen auf ${c.battery}%`); }}Schritt für Schritt, in Worten
- fleet ist ein Array: 2 normale und 2 elektrische Autos.
- c zeigt auf Skoda: instanceof sagt „nein“. Der Rumpf des if wird übersprungen.
- c zeigt auf Tesla: instanceof sagt „ja“. Eine neue Variable braucht es nicht: c.charge() lädt dasselbe Auto.
- c zeigt auf Dacia: instanceof sagt „nein“. Der Rumpf des if wird übersprungen.
- c zeigt auf Nissan: instanceof sagt „ja“. Eine neue Variable braucht es nicht: c.charge() lädt dasselbe Auto.
- Die Autos ändern sich nicht. Die Prüfung fragt das Objekt nur, was es ist.
Probier es aus
Ist es ein Auto?
Was gibt das Programm aus?
const c = new ElectricCar("Tesla", 35);const d = new Car("Skoda");console.log(c instanceof Car);console.log(c instanceof ElectricCar);console.log(d instanceof ElectricCar);Ein Elektroauto ist auch ein Auto, also ist die erste Prüfung wahr. Die Prüfung fragt nicht „ist es genau ein Car?“, sondern „kann man dieses Objekt als Car benutzen?“. Das normale Auto d ist nicht elektrisch, also ist die letzte Prüfung falsch.
Die Idee
Andere Formen, denen du begegnen wirst
Außer instanceof begegnen dir noch ein paar Arten, ein Objekt zu fragen:
const c = fleet[1];console.log(c.constructor.name);console.log(c.constructor === Car);console.log(c instanceof Car);console.log(typeof c.charge === "function", typeof fleet[0].charge === "function");console.log(typeof 42, typeof "Tesla", typeof true, typeof c);ElectricCarfalsetruetrue falsenumber string boolean objectc.constructorist die Klasse, aus der das Objekt erzeugt wurde, undc.constructor.nameihr Name.c.constructor === Carfragt „ist es genau einCar?“ und ist für das Elektroautofalse, währendc instanceof Cartrueist. Fast immer willst duinstanceof: Es akzeptiert auch Unterklassen.typeof c.charge === "function"fragt nicht nach der Klasse, sondern nur, ob das Objekt so eine Methode hat. Das ist die Prüfung gegen einen Vertrag aus der Lektion „Interfaces“: Jedes Objekt mitcharge()geht durch.typeofgibt die Art eines Werts als Text:"number","string","boolean","function". Für jedes Objekt ist es"object", also verrät es dir nicht die Klasse. Für die Klasse nimmst duinstanceof.
Genauer, für Neugierige
- Für
nullist die Prüfung immer falsch:null instanceof Caristfalse. Nach einem erfolgreicheninstanceofhast du also nienull. - Mit
instanceofkannst du nicht nach einem Vertrag fragen: Ein Vertrag sind nur Namen von Methoden, und es gibt keine Klasse zum Vergleichen. Dafür nimmst dutypeof a.swim === "function".
Probier es aus
Finde den Fehler
Das Programm zählt die normalen und die elektrischen Autos. Der Fuhrpark hat von beiden je zwei, aber es gibt aus:
Normale: 4, elektrische: 0In welcher Zeile ist der Fehler?
Wähle die Zeile mit dem Fehler.
Jedes Elektroauto ist auch ein Car, also ist die erste Prüfung für alle vier Autos wahr. Bis zur zweiten kommt das Programm nie. Prüf zuerst den genaueren Typ: Ist es ein ElectricCar, zähl es als elektrisch, sonst als normal.
Die Idee
Eine Prüfung oder eine Methode?
Du willst ausgeben, womit jedes Auto fährt. Eine Typprüfung kann das:
for (const c of fleet) { if (c instanceof ElectricCar) { console.log(`${c.brand}: Strom`); } else { console.log(`${c.brand}: Benzin`); }}Aber das ist das Gehalt mit einem if pro Rolle aus der Lektion über Polymorphie. Jedes Auto hat eine Energiequelle, nur eine andere. Das ist eine Aufgabe für eine Methode in Car, überschrieben in ElectricCar:
// in Carenergy() { return "Benzin";}
// in ElectricCarenergy() { return "Strom";}for (const c of fleet) { console.log(`${c.brand}: ${c.energy()}`);}Skoda: BenzinTesla: StromDacia: BenzinNissan: StromMorgen kommt ein Hybridauto dazu. Mit der Methode schreibst du eine neue Klasse. Mit den Prüfungen suchst du jedes if im Programm.
Die Regel:
- Jedes Objekt tut es, jedes auf seine Weise: eine Methode in der Basisklasse und Überschreiben.
- Nur manche Objekte können es (laden, in die Pedale treten): eine Typprüfung.
Probier es aus
Was fehlt?
for (const c of fleet) {
if (c ElectricCar) {
c.charge();
}
}instanceof: Es prüft, ob c auf ein ElectricCar zeigt. Wenn ja, funktioniert c.charge().Kurz gesagt
Die vier Säulen der OOP
Mit dieser Lektion hast du jede Idee aus den Modulen „Klassen und Objekte“ und „Vererbung und Polymorphie“ gesehen. Die objektorientierte Programmierung ruht auf vier davon. Du benutzt sie schon alle:
- Kapselung. Die Daten des Objekts sind versteckt, und von außen erreichst du sie nur über Methoden, die die Regeln bewachen.
Accounthält den Kontostand privat mit # und bietet nurdeposit()undwithdraw()an. Kapselung - Vererbung. Das Gemeinsame steht an einer Stelle, in der Basisklasse, und die Unterklasse fügt ihr Eigenes hinzu.
Managerist einEmployeemit Bonus. Vererbung - Polymorphie. Ein Aufruf, verschiedenes Verhalten je nach Objekt.
e.monthlyPay()in einer Schleife berechnet das Gehalt eines Mitarbeiters, eines Managers und einer Praktikantin. Polymorphie - Abstraktion. Du sagst, was das Objekt können muss, und jede Klasse entscheidet, wie. Die abstrakte
Shapeverspricht eine Fläche, der Vertrag für Zahlungen verspricht einen zu zahlenden Betrag. Abstrakte Klassen, Interfaces
Wie die vier in einem Programm zusammenarbeiten, wann jede wehtut und was verwechselt wird, steht in der letzten Lektion des Moduls: OOP-Prinzipien.
Übung
Was ist es wirklich?
Löse die Aufgaben in deinem Editor.
1. Parkplatz. Ein Array mit normalen und Familienautos (FamilyCar erbt von SimpleCar). Gib für jedes seinen Typ aus. Achte auf die Reihenfolge der Prüfungen.
Das ist ein SimpleCarDas ist ein FamilyCarDas ist ein SimpleCar2. Tänze. Ein Array mit normalen und Breakdance-Moves. Gib bei den Breakdance-Moves auch die Schwierigkeit aus. Nur BreakDanceMove hat sie, also frag nach der Prüfung danach.
moonwalk: DanceMovewindmill: BreakDanceMove, Schwierigkeit 8Salsa: DanceMove3. Fuhrpark. Nimm Car und ElectricCar aus der Übung in der Lektion „Vererbung“. Leg in ein Array einen „Skoda“ mit 40 l, einen „Tesla“ mit Effizienz 5, einen „Dacia“ mit 5 l und einen „Nissan“ mit Effizienz 4. Jedes Auto fährt 100 km: die elektrischen mit driveElectric, die übrigen mit drive. Dann gib die Kilometer und den Kraftstoff oder den Akku aus.
Skoda: 100 km, Kraftstoff 30 lTesla: 100 km, Akku 80%Nicht genug Kraftstoff für 100 kmDacia: 0 km, Kraftstoff 5 lNissan: 100 km, Akku 75%4. Zoo. Eine abstrakte Klasse Animal mit sound() und Unterklassen Cat, Dog und Fish. Nur Fish hat zusätzlich swim(): Er erfüllt den Vertrag „kann schwimmen“. Ruf in einer Schleife über die Tiere den Laut jedes Tiers auf, und bei denen, die schwimmen können, auch swim(). Der Vertrag hat keine Klasse, also benutzt die Prüfung typeof.
Miau, miau!Wau, wau!Der Fisch schweigt.Der Fisch schwimmt.Weitere Aufgaben
- Pedale. In der Übung aus der Lektion „Abstrakte Klassen“ hat
garage[0].pedal()das Programm angehalten, weil dort kein Fahrrad steht. Repariere es mit einer Typprüfung: In der Schleife über die Fahrzeuge fährt jedes Fahrzeug los, und nur das Fahrrad tritt zusätzlich in die Pedale. - Zahlungen nach Art. Aus der Lektion „Interfaces“: Das Array payments enthält Mitarbeiter und Rechnungen. Gib die Summe für Gehälter und die Summe für Rechnungen getrennt aus. Für Ivan, Maria und die zwei Rechnungen: 5500 € Gehälter und 2140 € Rechnungen.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Vererbung · Polymorphie · Abstrakte Klassen ohne abstract · Interfaces ohne interface
- Geht weiter in: OOP-Prinzipien · Werfen und eigene Exceptions · Hashcodes und Hashfunktionen · Daten, switch und Destrukturierung
- Aufgaben zum Thema: Vererbung und Polymorphie