Cvičenie č. 3 - Úvod do OOP
Dôležité pojmy
- trieda vs objekt vs inštancia (class vs object vs instance)
- konštruktor (constructor)
- preťažovanie metód a konštruktorov
- statické triedy a metódy
- virtuálne a abstraktné metódy
- 3 základné princípy OOP:
- zapúzdrenie (encapsulation)
- dedičnosť (inheritance)
- polymorfizmus (polymorphism)
Príklad č. 1: Objektová reprezentácia 2D geometrických útvarov
Navrhnite a naprogramujte reprezentáciu 2D geometrických útvarov: trojuhoľník, štvorec, obdĺžník a kruh. Každý útvar musí vedieť:
- spočítať svoj obsah
- uchovať si svoju farbu reprezentovanú výčtovým typom (enum)
- vedieť vypísať svoju farbu ako reťazec
Na záver napíšte metódu, ktorá dostane na vstup zoznam inštancií (napr. kruh, kruh, štvorec…) týchto útvarov a vráti súčet ich obsahov.
Riešenie:
namespace Class3
{
// Vyctovy typ reprezentujuci farbu.
enum Color {
BLACK, RED, BLUE, WHITE
}
// Spolocny interface pre vsetky 2D objekty.
interface Object2D {
// Vrati obsah 2D objektu.
double calculateArea();
// Vrati farbu objektu ako string.
string getColorAsString();
}
// Spolocna abstraktna trieda, ktora implementuje interface Object2D.
// V tejto triede naimplementujeme ukladanie a vypisovanie farby objektu,
// ktore bude rovnake pre vsetky 2D objekty.
abstract class Object2DBase : Object2D
{
// Premenna pre ulozenie farby objektu.
// Miesto privlastku private pouzijeme protected, aby bola tato premenna
// pristupna aj z objektov, ktore budu dedit od Object2DBase.
protected Color color = Color.BLACK;
// Implementaciu metody calculateArea este nebudeme implementovat a
// preto ju oznacime klucovym slovom abstract a nechame
// ju bez implementacie.
public abstract double calculateArea();
// Naimplementujeme metodu getColorAsString interfacu Object2D.
public string getColorAsString()
{
switch (this.color)
{
case Color.BLUE:
return "Modra";
case Color.WHITE:
return "Biela";
case Color.RED:
return "Cervena";
case Color.BLACK:
return "Cierna";
default:
return "Neznama farba";
}
}
}
// Implementacia kruhu podla interfacu Object2D.
// Trieda Circle dedi priamo od Object2DBase a tranzitivne aj
// interface Object2D. Takto Circle zdedi vsetok kod, ktory pracuje
// s farbou.
class Circle : Object2DBase
{
// Polomer kruhu.
private double radius = 0.0;
// Prvy konstruktor, ktory inicializuje kruh s polomerom radius
// a defaultnou farbou.
public Circle(double radius)
{
this.radius = radius;
}
// Druhy konstruktor, ktory inicializuje kruh s polomerom radius
// a farbou color.
// this(radius) zavola prvy konstruktor s parametrom radius, aby sme
// neopakovali kod this.radius = radius;
public Circle(double radius, Color color) : this(radius)
{
this.color = color;
}
// Implementacia vypoctu obsahu kruhu.
// Pouzivame klucove slovicko override, ktore explicitne hovori,
// ze prepisujeme (overridujeme) metodu calculateArea interfacu Object2D.
public override double calculateArea()
{
return Math.PI * Math.Pow(this.radius, 2);
}
}
// Dalsi priklad implementacie trojuholniku.
class Triangle : Object2DBase
{
double a, b, c = 0.0;
public Triangle(double a, double b, double c)
{
this.a = a;
this.b = b;
this.c = c;
}
public Triangle(double a, double b, double c, Color color) : this(a, b, c)
{
this.color = color;
}
public override double calculateArea()
{
// Heron's formula
double s = (a + b + c) / 2;
return Math.Sqrt(s * (s - a) * (s - b) * (s - c));
}
}
class Program
{
// Metoda pocitajuca sumu obsahov objektov, ktore dostane na vstup v poli.
// Vsimnite si, ze tato metoda pracuje s objektami, len cez interface
// Object2D a vobec ju nezaujima, ci je objekt typu Circle alebo Triangle.
// Jedine co tuto metodu zaujima je, ze tieto objekty
// implementuju metodu calculateArea.
public static double calculateSum(Object2D[] objects)
{
double sum = 0.0;
foreach (Object2D obj in objects)
{
sum = sum + obj.calculateArea();
}
return sum;
}
static void Main(string[] args)
{
// Vytvorime pole typu Object2D, do ktoreho
// mozeme vkladat instancie vsetkych tried, ktore
// interface Object2D implementuju.
Object2D[] objs = new Object2D[5];
objs[0] = new Circle(19, Color.BLUE);
objs[1] = new Circle(15);
objs[2] = new Triangle(5, 5, 5);
objs[3] = new Triangle(2, 1.5, 1.5, Color.RED);
objs[4] = new Triangle(3, 3, 3, Color.WHITE);
double sumOfAreas = calculateSum(objs);
Console.WriteLine("Sum of areas: " + sumOfAreas);
Console.WriteLine("Colors:");
foreach (Object2D obj in objs)
{
Console.WriteLine(obj.getColorAsString());
}
Console.ReadLine();
}
}
}
Príklad č. 2: Objektová reprezentácia a implementácia listu
Napíšte 2 rôzne implementácie rozhrania pre štruktúru reprezentujúcu list celých čísel, tzn. int-ov podľa interfacu definovaného nižšie. Prvá implementácia musí byť spojákom (LinkedList) a druhá poľom (ArrayList).
Ak si všimnete nejaký kód, ktorý by si dal vyabstrahovať a použiť pre obe implementácie (hint: metóda print), tak ho vložte do abstraktnej triedy, ktorú si vytvorte (podobne ako u príkladu č. 1).
namespace Class3
{
// Spolocny interface pre datovu strukturu reprezentujucu list int-ov.
public interface IList
{
// Vlozi jeden prvok na koniec listu.
void add(int element);
// Vrati prvok v zozname na danom indexe, index zacina na 0.
// Ak zadame neplatny index, napr. mensi ako 0 alebo vacsi ako je
// pocet prvkov v liste, tak vrati 0.
int get(int index);
// Vrati pocet prvkov v liste.
int size();
// Odstrani prvy vyskyt prvku v liste.
void remove(int element);
// Vypise list na jednom riadku do konzole.
void print();
}
// Implementacia listu pomocou spojoveho zoznamu.
class LinkedList : IList
{
// Trieda reprezentujuca jeden uzol v zozname.
// Triedu si kludne upravte/prisposobte, ako potrebujete.
class Node
{
private int value = 0; // ulozena hodnota v uzle.
private Node next = null; // referencia na dalsi prvok v zozname.
// V tomto pripade budete pouzivat referenciu miesto pointra ako
// to bolo v pascale. Poslednemu prvku nastavte hodnotu next
// na null. Ci ste na konci zoznamu mozete potom kontrolovat
// pomocout next != null
// Konstruktor pre vytvorenie uzlu.
public Node(int value, Node next)
{
this.value = value;
this.next = next;
}
// Metoda pre citanie hodnoty uzlu.
public int getValue()
{
return value;
}
// Metoda pre citanie nasledovnika.
public Node getNext()
{
return next;
}
}
// Koren spojaku.
private Node root = null;
public void add(int element)
{
throw new NotImplementedException();
}
public int get(int index)
{
throw new NotImplementedException();
}
public void print()
{
throw new NotImplementedException();
}
public void remove(int element)
{
throw new NotImplementedException();
}
public int size()
{
throw new NotImplementedException();
}
}
// Implementacia listu pomocou pola.
// V tomto pripade budete prvky listu ukladat do pola.
// Kedze neviete kolko prvkov do listu pojde, tak si musite
// toto pole najprv nainicializovat na nejaku dlzku.
// Ak pocet prvkov v liste prekroci dlzku pola,
// tak nainicializujete nove dlhsie pole (napr. 2 krat dlshie),
// stare pole prekopirujete do noveho pola a pokracujete dalej.
class ArrayList : IList
{
// Dlzka prveho pola, ktore inicializujete.
private const int INIT_SIZE = 2;
// Pole do ktoreho budete ukladat prvky listu.
private int[] arr = new int[INIT_SIZE];
public void add(int element)
{
throw new NotImplementedException();
}
public int get(int index)
{
throw new NotImplementedException();
}
public void print()
{
throw new NotImplementedException();
}
public void remove(int element)
{
throw new NotImplementedException();
}
public int size()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
// Testovaci kod.
IList list = new LinkedList();
// Implementacia s ArrayList-om musi davat rovnake vystupy.
// IList list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(1);
list.print(); // vypise "1 2 3 4 1"
Console.WriteLine("Size:" + list.size()); // vypise 5
list.remove(1);
list.remove(3);
list.print(); // vypise "2 4 1"
Console.WriteLine("Size:" + list.size()); // vypise 3
// vypise 4
Console.WriteLine("Element on index 1 is: " + list.get(1));
Console.ReadLine();
}
}
}
Domáca úloha č. 1
Doprogramujte úlohu č. 2 a a riešenie mi pošlite mailom. Pošlite mi zabalený (prosím .zip) projekt Visual Studia. Vaše riešenie si doneste na ďaľšie cvičenie, budeme s ním pokračovať ďalej.
Termín odovzdania: 12. 3. 2017(23:59)
Spôsob odovzdania: zdrojový kód mailom
Počet bodov: 20