Podstawy programowania obiektowego

Transkrypt

Podstawy programowania obiektowego
Podstawy programowania obiektowego
wykład 5 – klasy i obiekty
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// współrzędne punktu
int x, y;
x = 3;
y = 2;
}
}
}
Jak, korzystając z
dotychczasowej wiedzy,
zdefiniować w programie
punkt?
Może tak?
// wypisanie informacji
Console.WriteLine("Punkt ({0}, {1})", x, y);
Console.ReadKey();
A co, jeśli punktów jest więcej?
A co, jeśli punkt może mieć kolor,
nazwę, znacznik widoczności, etc?
1/28
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// tworzenie punktu
Punkt p1 = new Punkt();
p1.x = 3;
p1.y = 2;
Rozwiązanie:
stworzenie klasy
reprezentującej punkt.
Tworzenie obiektu klasy Punkt.
// wypisanie informacji
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
Console.ReadKey();
}
}
class Punkt
{
public int x, y;
}
}
Definicja klasy Punkt.
2/28
namespace ConsoleApplication1
{
class Program
p1
{
static void Main(string[] args)
{
// tworzenie punktu
Punkt p1 = new Punkt(); Ta instrukcja powołuje do
życia obiekt Punkt –
p1.x = 3;
strukturę zawierającą dwie
p1.y = 2;
wartości typu int (zgodnie z
definicją).
// wypisanie informacji
Console.WriteLine("Punkt ({0}, {1})", p1.x,
Console.ReadKey();
}
}
class Punkt
{
public int x, y;
}
}
Punkt
x
y
p1.y);
3/28
namespace ConsoleApplication1
{
class Program
p1
{
Punkt
static void Main(string[] args)
x 3
{
// tworzenie punktu
y 2
Punkt p1 = new Punkt();
Kropka pozwala odwołać się
p1.x = 3;
do składników (składowych)
p1.y = 2;
obiektu.
// wypisanie informacji
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
Console.ReadKey();
}
}
class Punkt
{
public int x, y;
}
Punkt (3, 2)
}
4/28
class Program
{
static void Main(string[] args)
{
// tworzenie punktów
Punkt p1 = new Punkt();
Punkt p2 = new Punkt();
p1.x = 3;
p1.y = 2;
p2.x = 5;
p2.y = 1;
p1
Punkt
x 3
y 2
p2
Na podstawie tej samej
definicji klasy możemy
stworzyć wiele obiektów.
Punkt
x 5
y 1
// wypisanie informacji
Console.WriteLine("Punkt 1 ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Punkt 2 ({0}, {1})", p2.x, p2.y);
Console.ReadKey();
}
}
class Punkt
{
public int x, y;
}
Punkt (3, 2)
Punkt (5, 1)
5/28
class Punkt
Klasa to nie tylko struktura.
{
Klasy mogą mieć metody.
public int x, y;
// przesuń punkt o wektor [dx, dy]
public void Przesuń(int dx, int dy)
{
x += dx;
p1
p1
y += dy;
Punkt
Punkt
}
}
x 3
x 4
class Program
y 2
y 2
{
static void Main(string[] args)
{
Punkt p1 = new Punkt();
Punkt (3, 2)
p1.x = 3; p1.y = 2;
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
p1.Przesuń(1, 0);
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
}
}
Punkt (4, 2)
6/28
class Punkt
{
public int x, y;
// przesuń punkt o wektor [dx, dy]
public void Przesuń(int dx, int dy)
{
x += dx;
y += dy;
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt();
p1.x = 3; p1.y = 2;
Jak to działa?
p1
Punkt
x 3
y 2
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
p1.Przesuń(1, 0);
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
}
}
7/28
class Punkt
{
public int x, y;
// przesuń punkt o wektor [dx, dy]
public void Przesuń(int dx, int dy)
{
dx 1 dy 0
x += dx;
y += dy;
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt();
p1.x = 3; p1.y = 2;
Jak to działa?
this
Punkt
x 3
y 2
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
p1.Przesuń(1, 0);
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
}
}
8/28
class Punkt
{
public int x, y;
// przesuń punkt o wektor [dx, dy]
public void Przesuń(int dx, int dy)
{
dx 1 dy 0
x += dx;
y += dy;
Można też zapisać:
}
this.x += dx;
}
this.y += dy;
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt();
p1.x = 3; p1.y = 2;
Jak to działa?
this
Punkt
x 4
y 2
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
p1.Przesuń(1, 0);
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
}
}
9/28
class Punkt
{
public int x, y;
// przesuń punkt o wektor [dx, dy]
public void Przesuń(int dx, int dy)
{
x += dx;
y += dy;
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt();
p1.x = 3; p1.y = 2;
Jak to działa?
p1
Punkt
x 4
y 2
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
p1.Przesuń(1, 0);
Console.WriteLine("Punkt ({0}, {1})", p1.x, p1.y);
}
}
10/28
class Punkt
Specjalnym typem
{
metody jest konstruktor.
public int x, y;
public void Przesuń(int dx, int dy) { ... }
public Punkt()
{
Console.WriteLine("to jest konstruktor");
}
}
p1
p2
class Program
{
Punkt
Punkt
static void Main(string[] args)
x 3
x 5
{
y 2
y 1
Punkt p1 = new Punkt();
Punkt p2 = new Punkt();
p1.x = 3; p1.y = 2;
p2.x = 5; p2.y = 1;
to jest konstruktor
to jest konstruktor
Console.WriteLine("Punkt 1 ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Punkt 2 ({0}, {1})", p2.x, p2.y);
}
}
11/28
class Punkt
Przeważnie zadaniem
{
konstruktora jest
public int x, y;
inicjalizacja
zmiennych.
public void Przesuń(int dx, int dy) { ...
}
public Punkt(int x, int y)
{
Można też zapisać w mniej niejednoznaczny sposób:
this.x = x;
public Punkt(int xx, int yy)
this.y = y;
{
}
x = xx;
}
y = yy;
class Program
}
p1
p2
{
static void Main(string[] args)
Punkt
Punkt
{
x 3
x 5
Punkt p1 = new Punkt(3, 2);
y 2
y 1
Punkt p2 = new Punkt(5, 1);
Console.WriteLine("Punkt 1 ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Punkt 2 ({0}, {1})", p2.x, p2.y);
}
}
12/28
class Punkt
Przeważnie zadaniem
{
konstruktora jest
public int x, y;
inicjalizacja
zmiennych.
public void Przesuń(int dx, int dy) { ...
}
public Punkt(int x, int y)
{
x 3
y 2
this.x = x;
this.y = y;
}
}
class Program
this
{
static void Main(string[] args)
Punkt
{
x
Punkt p1 = new Punkt(3, 2);
y
Punkt p2 = new Punkt(5, 1);
Console.WriteLine("Punkt 1 ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Punkt 2 ({0}, {1})", p2.x, p2.y);
}
}
13/28
class Punkt
{
public int x, y;
}
Ciekawostka:
konstruktor domyślny.
... main ...
Punkt p = new Punkt();
class Punkt
{
public int x, y;
public Punkt(int x, int y)
{
this.x = x;
this.y = y;
}
}
Dlaczego przestało to działać?
... main ...
Punkt p = new Punkt();
14/28
class Punkt
Specjalna metoda: ToString().
{
public int x, y;
public void Przesuń(int dx, int dy) { ... }
public Punkt(int x, int y) { ... }
public override string ToString()
{
return "jak to działa?";
}
}
class Program
{
Punkt jak to działa?
static void Main(string[] args)
{
Punkt p1 = new Punkt(3, 2);
Console.WriteLine("Punkt {0}", p1);
}
}
Można to też zapisać:
Console.WriteLine("Punkt {0}", p1.ToString());
15/28
class Punkt
Zadaniem metody ToString()
{
jest zwrócenie tekstowej
public int x, y;
reprezentacji
public void Przesuń(int dx, int dy) {
... } obiektu.
public Punkt(int x, int y) { ... }
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt(3, 2);
Console.WriteLine("Punkt {0}", p1);
}
}
Punkt (3, 2)
16/28
class Punkt
{
private int x, y;
public void Przesuń(int dx, int dy)
{
x += dx; y += dy;
}
public Punkt(int xx, int yy)
{
x = xx; y = yy;
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt(3, 2);
p1.Przesuń(1, 0);
Console.WriteLine(p1);
}
}
Pojęcie hermetyzacji.
To, co jest istotne dla
użytkownika klasy, nosi nazwę
inte rfe jsu. Jest to
funkcjonalność, z jakiej można
skorzystać. Powinien być
publiczny i nie powinien się zbyt
często zmieniać.
17/28
class Punkt
{
private int x, y;
public void Przesuń(int dx, int dy)
{
x += dx; y += dy;
}
public Punkt(int xx, int yy)
{
x = xx; y = yy;
}
public override string ToString()
{
return "(" + x + ", " + y + ")";
}
}
class Program
{
static void Main(string[] args)
{
Punkt p1 = new Punkt(3, 2);
p1.Przesuń(1, 0);
Console.WriteLine(p1);
}
}
Pojęcie hermetyzacji.
Implementacja nie jest ważna
dla użytkownika klasy. Jest
prywatną sprawą twórcy klasy
i może zmieniać się bez
ostrzeżenia. To ona sprawia, że
interfejs działa.
18/28
class Program
Przykład: Klasa Konto.
{
static void Main(string[] args)
{
Konto konto = new Konto();
konto.Wpłać(1000);
konto.Wypłać(250);
Console.WriteLine(konto.Saldo());
Console.WriteLine(konto);
}
}
class Konto
{
...
public void Wpłać(double kwota) { ... }
public void Wypłać(double kwota) { ... }
public double Saldo() { ... }
public override string ToString() { ... }
}
19/28
class Program
Przykład: Klasa Konto.
{
static void Main(string[] args)
{
Konto konto = new Konto();
konto.Wpłać(1000);
konto.Wypłać(250);
Console.WriteLine(konto.Saldo());
Console.WriteLine(konto);
}
}
class Konto
{
private double suma;
public void Wpłać(double kwota) { suma += kwota; }
public void Wypłać(double kwota) { suma -= kwota; }
public double Saldo() { return suma; }
public override string ToString()
{
return suma.ToString("F2");
}
}
20/28
class Konto
Przykład: Klasa Konto.
{
private double suma;
public void Wpłać(double kwota) { suma += kwota; }
public void Wypłać(double kwota)
{
if (kwota <= 0 || kwota > suma)
{
Console.WriteLine("Nie możesz wypłacić.");
return;
}
suma -= kwota;
}
public double Saldo() { return suma; }
public override string ToString()
{
return suma.ToString("F2");
}
}
Jaką to:
Konto.Wypłać(250);
ma przewagę nad tym?
Konto.suma -= 250;
21/28
class Program
Przykład: Klasa Zespolona.
{
static void Main(string[] args)
{
Zespolona z1 = new Zespolona(),
z2 = new Zespolona(2, 1),
z3 = new Zespolona(3);
z1.Dodaj(z2);
z2 = z1.Plus(z3);
Console.WriteLine(z2);
}
}
5+1i
class Zespolona
{
...
public Zespolona() ...
public Zespolona(double r) ...
public Zespolona(double r, double i) ...
public void Dodaj(Zespolona z) ...
public Zespolona Plus(Zespolona z) ...
public override string ToString() ...
}
22/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona()
{
this.re = 0;
Konstruktory
this.im = 0;
}
public Zespolona(double r)
{
this.re = r;
this.im = 0;
}
public Zespolona(double r, double i)
{
this.re = r;
this.im = i;
}
public void Dodaj(Zespolona z) ...
public Zespolona Plus(Zespolona z) ...
public override string ToString() ...
}
23/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona() { }
Można tak, gdyż
public Zespolona(double r)
składowe domyślnie
{
są zerowane.
this.re = r;
this.im = 0;
}
public Zespolona(double r, double i)
{
this.re = r;
this.im = i;
}
public void Dodaj(Zespolona z) ...
public Zespolona Plus(Zespolona z) ...
public override string ToString() ...
}
24/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona() { }
public Zespolona(double r) : this(r, 0) { }
public Zespolona(double r, double i)
{
Zadanie
this.re = r;
pozostawione
this.im = i;
innemu
}
konstruktorowi.
public void Dodaj(Zespolona z) ...
public Zespolona Plus(Zespolona z) ...
public override string ToString() ...
}
25/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona() { }
public Zespolona(double r) : this(r, 0) { }
public Zespolona(double r, double i) { ... }
public void Dodaj(Zespolona z) ...
public Zespolona Plus(Zespolona z) ...
Bez znaku „+”
public override string ToString()
jeśli wartość
{
urojona jest
if (im >= 0)
ujemna.
return re + "+" + im + "i";
return re + "" + im + "i";
}
}
26/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona() { }
public Zespolona(double r) : this(r, 0) { }
public Zespolona(double r, double i) { ... }
public void Dodaj(Zespolona z)
{
this.re += z.re;
Dodajemy „do
this.im += z.im;
samego siebie”.
}
public Zespolona Plus(Zespolona z) ...
public override string ToString() { ... }
}
this
z
Zespolona
re
im
Zespolona
re
im
27/28
class Zespolona
Przykład: Klasa Zespolona.
{
private double re, im;
public Zespolona() { }
public Zespolona(double r) : this(r, 0) { }
public Zespolona(double r, double i) { ... }
public void Dodaj(Zespolona z) { ... }
public Zespolona Plus(Zespolona z)
{
Musimy zwrócić sumę
Zespolona wynik = new Zespolona();
„siebie i przekazanego
wynik.re = this.re + z.re;
argumentu” - jakąś
wynik.im = this.im + z.im;
nową zmienną
return wynik;
zespoloną.
}
public override string ToString() { ... }
}
this
z
Zespolona
re
im
wynik
Zespolona
re
im
Zespolona
re
im
28/28