Instanzmethoden
Kurz gesagt: Eine Instanzmethode (ohne static) arbeitet mit den Daten des konkreten Objekts vor dem Punkt, und ToString sagt, wie sich das Objekt selbst ausgibt.
Problem
Jeder hebt auf seine Art ab
Die Bank hat eine Klasse Account mit Inhaber und Kontostand. An zwei Stellen im Programm wird Geld abgehoben. Der Geldautomat prüft, ob genug Geld da ist. Die Kartenzahlung hat jemand anderes geschrieben, und sie prüft nicht:
Account account = new Account("Maria", 100);
// Der Geldautomat prüft, ob genug Geld da ist.if (account.Balance >= 70){ account.Balance -= 70;}
// Die Kartenzahlung hat jemand anderes geschrieben, und eine Prüfung gibt es nicht.account.Balance -= 50;
Console.WriteLine(account.Balance);-20Das Konto ist im Minus. Die Regel „Du kannst nicht mehr abheben, als du hast“ ist wichtig, aber sie steht (oder fehlt) an jeder Stelle, die abhebt, einzeln.
Die Idee
Methoden wohnen bei den Daten
Die Logik des Abhebens gehört zum Konto, also kommt sie in die Klasse Account. Eine Methode in der Klasse ohne static ist eine Instanzmethode:
class Account{ public string Owner; public double Balance;
public Account(string owner, double balance) { Owner = owner; Balance = balance; }
public void Deposit(double amount) { Balance += amount; }
public void Withdraw(double amount) { if (amount <= Balance) { Balance -= amount; } else { Console.WriteLine("Nicht genug Geld: " + Owner); } }}
class Program{ static void Main() { Account account = new Account("Maria", 100); account.Withdraw(70); account.Withdraw(50); account.Deposit(20); Console.WriteLine(account.Balance); }}Nicht genug Geld: Maria50- Du rufst die Methode mit einem Punkt auf einem Objekt auf:
account.Withdraw(70), genau wie die Felder. - Innen ist
Balanceder Kontostand dieses Kontos, des Objekts vor dem Punkt. Du kannst auchthis.Balanceschreiben. - Die Prüfung steht einmal da. Wer über die Methode abhebt, geht durch sie hindurch.
Account maria = new Account("Maria", 100);Account peter = new Account("Peter", 40);maria.Withdraw(70);peter.Withdraw(70);Console.WriteLine(maria.Balance + " " + peter.Balance);Schritt für Schritt, in Worten
- Zwei Konten, zwei Objekte. Jedes hat seinen eigenen Kontostand.
- maria.Withdraw(70): this bekommt einen Pfeil auf das Objekt vor dem Punkt.
- In der Methode gehört der Kontostand zu this: 100 - 70 = 30.
- Dieselbe Methode, ein anderes Objekt: Jetzt zeigt this auf Peter.
- 70 ist mehr als 40: Die Methode gibt eine Ablehnung aus, und der Kontostand von Peter bleibt gleich.
- Den Code der Methode gibt es einmal. Die Felder gehören dem Objekt, auf dem du sie aufrufst.
Die Kartenzahlung kann die Prüfung nicht mehr „vergessen“, wenn sie mit Withdraw abhebt. Sie kann aber immer noch direkt ins Feld schreiben. Wie du das verhinderst, siehst du in der Lektion „Kapselung“.
Die Idee
Instanzmethode oder statische Methode
Die Methoden aus dem Modul „Methoden“ waren static. Sie bekommen alles als Parameter und haben kein eigenes Objekt. Eine Instanzmethode arbeitet mit den Feldern des Objekts, auf dem sie aufgerufen wurde:
static double ApplyDiscount(double price, double percent){ return price * (100 - percent) / 100;}
double price = ApplyDiscount(10, 10);account.Withdraw(70);Eine Instanzmethode kannst du nicht über den Namen der Klasse aufrufen. Es ist nicht klar, von welchem Konto abgehoben werden soll:
Account.Withdraw(70);error CS0120: An object reference is required for the non-static field, method, or property 'Account.Withdraw(double)'Was static genau bedeutet und wann du es brauchst, kommt in der Lektion „static: was alle Objekte teilen“.
Probier es aus
Wessen Konto?
Was gibt das Programm aus?
Account maria = new Account("Maria", 100);Account peter = new Account("Peter", 40);maria.Deposit(30);peter.Withdraw(10);Console.WriteLine(maria.Balance + " " + peter.Balance);Jedes Objekt hat seinen eigenen Kontostand. maria.Deposit(30) ändert nur den Kontostand von Maria, und peter.Withdraw(10) nur den von Peter. Peter hat 40, also klappt das Abheben von 10.
Probier es aus
Finde den Fehler
Wähle die Zeile mit dem Fehler.
static vor der Methode bedeutet, dass sie kein Objekt hat. Dann gibt es auch keinen Kontostand, den sie sehen könnte. Der Compiler hält in der Zeile mit dem Kontostand an:
error CS0120: An object reference is required for the non-static field, method, or property 'Account.Balance'Der Fehler steht aber im Kopf der Methode: Entferne static.
Die Idee
Eine Methode kann auch antworten
Eine Instanzmethode kann ein Ergebnis zurückgeben, genau wie die Methoden aus dem Modul „Methoden“. Ein Produkt kennt seinen Preis und seine Stückzahl, also kann es dir seine eigenen Kosten sagen:
class Product{ // die Felder und der Konstruktor, wie vorher
public double Total() { return Price * Quantity; }}
Product[] cart ={ new Product("Brot", 1.20, 2), new Product("Milch", 2.10, 1), new Product("Kaffee", 7.50, 1)};double sum = 0;foreach (Product p in cart){ sum += p.Total();}Console.WriteLine("Gesamt: " + sum + " €");Gesamt: 12 €Vergleich das mit der ersten Lektion des Moduls: Dort wurde die Summe in Main aus den Feldern berechnet. Jetzt fragt Main nur noch jedes Produkt. Kommt morgen ein Mengenrabatt dazu, änderst du nur Total().
Die Idee
Wie sieht das Objekt als Text aus?
Wenn du ein Produkt direkt ausgibst, bekommst du etwas Nutzloses:
Product coffee = new Product("Kaffee", 7.50, 1);Console.WriteLine(coffee);ProductC# gibt nur den Namen der Klasse aus.
Die Klasse kann sagen, wie sie angezeigt werden soll. Die Methode heißt ToString() und gibt Text zurück:
class Product{ // die Felder und der Konstruktor, wie vorher
public double Total() { return Price * Quantity; }
public override string ToString() { return Name + " x" + Quantity + ": " + Total() + " €"; }}
Product coffee = new Product("Kaffee", 7.50, 1);Product bread = new Product("Brot", 1.20, 2);Console.WriteLine(coffee);Console.WriteLine("Im Warenkorb: " + bread);Kaffee x1: 7.5 €Im Warenkorb: Brot x2: 2.4 €Du rufst sie nicht selbst auf. Console.WriteLine(coffee) und "Im Warenkorb: " + bread rufen sie für dich auf, wenn das Objekt zu Text werden muss.
Schreib override vorerst genau so in den Kopf. Was es bedeutet, kommt im Modul „Vererbung und Polymorphie“.
Probier es aus
Ein Buch in einem Satz
Was gibt das Programm aus?
class Book{ public string Title; public string Author;
public Book(string title, string author) { Title = title; Author = author; }
public override string ToString() { return Title + " von " + Author; }}
Book book = new Book("Der Zauberberg", "Thomas Mann");Console.WriteLine("Ich lese: " + book);"Ich lese: " + book muss book zu Text machen. Also wird ToString() des Buches aufgerufen, und es gibt Titel und Autor zurück.Übung
Objekte, die etwas tun
Löse die Aufgaben in deinem Editor. Nimm die Klassen aus den früheren Lektionen und gib ihnen Methoden.
Person: eine MethodeIntroduce(), die Name und Alter ausgibt.SimpleCar: eine MethodeAccelerate(), die die Geschwindigkeit um 10 erhöht. Jetzt fasst Main die Geschwindigkeit nicht mehr direkt an.DanceMove: eine MethodePerform(), die den Schritt „ausführt“.Book: eine MethodeRead(), die „Ich lese gerade [Titel] von [Autor]“ ausgibt.
Erzeuge von jeder Klasse ein Objekt und ruf seine Methoden auf:
Hallo, ich bin Maria und bin 34 Jahre alt.Geschwindigkeit nach dem Beschleunigen: 10Ich tanze moonwalk für 5 SekundenIch lese gerade Der Prozess von Franz KafkaÜbung
Ein Auto mit Tank
Eine Klasse Car mit Marke, Geschwindigkeit, Kraftstoff (in Litern) und Kilometerstand. Der Konstruktor bekommt Marke und Kraftstoff. Geschwindigkeit und Kilometerstand beginnen bei 0.
Accelerate()erhöht die Geschwindigkeit um 10.Refuel(double liters)tankt nach, aber in den Tank passen höchstens 50 Liter.Drive(int distance)verbraucht 6 Liter auf 100 km und addiert die Strecke zum Kilometerstand. Reicht der Kraftstoff nicht, gibt die Methode eine Meldung aus, und das Auto fährt nicht.ToString()gibt Marke, Kilometerstand und Kraftstoff zurück.
Car car = new Car("Toyota", 20);car.Accelerate();car.Accelerate();Console.WriteLine("Geschwindigkeit: " + car.Speed);car.Drive(100);Console.WriteLine(car);car.Drive(300);car.Refuel(40);Console.WriteLine(car);car.Drive(300);Console.WriteLine(car);Geschwindigkeit: 20Toyota: 100 km, 14 lNicht genug Kraftstoff für 300 kmToyota: 100 km, 50 lToyota: 400 km, 32 ldistance * 6 / 100.0. Mit 100 statt 100.0 ist die Division eine Ganzzahldivision, und für 30 km bekommst du 1 Liter statt 1,8.Weitere Aufgaben
- Rabatt. Gib
Producteine MethodeApplyDiscount(double percent), die den Preis des Produkts senkt. Vergleich sie mit der statischen Methode aus dem Modul „Methoden“, die einen neuen Preis zurückgegeben hat. - Ein Konto mit Verlauf. Gib
Accounteinen Zähler für Vorgänge: Jede Einzahlung und jede erfolgreiche Abhebung erhöht ihn um 1. Eine MethodeToString()gibt Inhaber, Kontostand und Anzahl der Vorgänge zurück.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Methoden · Parameter und return · Klassen und Objekte · Konstruktoren und this
- Geht weiter in: Kapselung · static: was alle Objekte teilen · Vererbung · Polymorphie
- Aufgaben zum Thema: Klassen und Objekte