Search
V této části kapitoly se naučíte vytvářet objekty a definovat vazby mezi nimy.
cars
cz.cvut.fel.pjv.cars
Main
main
cz.cvut.fel.pjv.cars.model
Car
manufacturer
modelName
year
vinCode
UUID.randomUUID()
toString
getNumberOfExistingCars()
equals
hashcode
Car car1 = new Car("Volkswagen", "Polo", 2010); System.out.println(car1); System.out.println("Počet aut: " + Car.getNumberOfExistingCars()); Car car2 = new Car("Chevrolet", "Corvette", 1980); System.out.println(car2); System.out.println("Počet aut: " + Car.getNumberOfExistingCars());
Volkswagen Polo year 2010 VIN: 38e8a15e-521c-466a-98e0-f78c03fcdb94. Počet aut: 1 Chevrolet Corvette year 1980 VIN: 38d302ff-e1e1-41b5-b53b-5df1a3add882. Počet aut: 2
Engine
type
ServiceBook
serviceRecords
ServiceBook(Car car)
Car car1 = new Car("Volkswagen", "Polo", 2010, "AKK"); ServiceBook serviceBook1 = new ServiceBook(car1); serviceBook1.addRecord("První servisní prohlídka."); System.out.println(car1); System.out.println("Počet aut: " + Car.getNumberOfExistingCars()); System.out.printf("Servisní záznamy %s %s:\n%s\n", car1.getManufacturer(), car1.getModelName(), car1.getServiceBook()); Car car2 = new Car("Chevrolet", "Corvette", 1980, "LS7"); ServiceBook serviceBook2 = new ServiceBook(car2); serviceBook2.addRecord("První servisní prohlídka."); serviceBook2.addRecord("Porucha motoru."); System.out.println(car2); System.out.println("Počet aut: " + Car.getNumberOfExistingCars()); System.out.printf("Servisní záznamy %s %s:\n%s\n", car2.getManufacturer(), car2.getModelName(), car2.getServiceBook());
Volkswagen Polo year 2010 VIN: 5ab16b5f-c504-41f3-ab28-8111c3fb4ab1. Počet aut: 1 Servisní záznamy Volkswagen Polo: První servisní prohlídka. Chevrolet Corvette year 1980 VIN: d18fe38c-dedc-42f3-90b4-0f63b2e40cfa. Počet aut: 2 Servisní záznamy Chevrolet Corvette: První servisní prohlídka. Porucha motoru.
cz.cvut.fel.pjv.cars.data
RaceResult
cz.cvut.fel.pjv.utils
ArrayUtil
sort
Comparable
speed
CarListNode
CarLinkedList
toArray()
Race
length
addRacingCar(Car car)
true
false
getWinner()
getWinningTime()
getRaceResults()
Car car1 = new Car("Volkswagen", "Polo", 2010, "AKK", 40); Car car2 = new Car("Chevrolet", "Corvette", 1980, "LS7", 45); Car car3 = new Car("Trabant", "P601", 1990, "Air cooled, 0.6-liter 2-stroke", 20); Car car4 = new Car("BMW", "3", 2006, "318d", 42); Car car5 = new Car("McLaren", "F1", 2014, "V12", 107); Race race = new Race(1000); race.addRacingCar(car1); race.addRacingCar(car2); race.addRacingCar(car3); race.addRacingCar(car4); race.addRacingCar(car5); System.out.println("Závodníci:"); System.out.println(race); System.out.printf("Výhercem se stává %s s časem %s.\n", race.getWinner(), race.getWinningTime()); System.out.printf("Pořadí v cíli:\n%s\n", race);
Závodníci: Volkswagen Polo year 2010 VIN: 2b8a89b2-f15d-4a5a-a14e-8de9aca023d8 Chevrolet Corvette year 1980 VIN: 75e880b1-822d-49b5-9b5e-e8cca5f48e99 Trabant P601 year 1990 VIN: fce81b1e-2916-492a-974a-cac9d623608d BMW 3 year 2006 VIN: 7fb6c0b3-092a-4fb6-8e7f-590443ecadcc McLaren F1 year 2014 VIN: be54715d-54b1-40d3-9323-029f27a124c3 Výhercem se stává McLaren F1 year 2014 VIN: be54715d-54b1-40d3-9323-029f27a124c3 s časem 0 hours 0 minutes 9 seconds. Pořadí v cíli: McLaren F1 year 2014 VIN: be54715d-54b1-40d3-9323-029f27a124c3, time: 0 hours 0 minutes 9 seconds. Chevrolet Corvette year 1980 VIN: 75e880b1-822d-49b5-9b5e-e8cca5f48e99, time: 0 hours 0 minutes 22 seconds. BMW 3 year 2006 VIN: 7fb6c0b3-092a-4fb6-8e7f-590443ecadcc, time: 0 hours 0 minutes 23 seconds. Volkswagen Polo year 2010 VIN: 2b8a89b2-f15d-4a5a-a14e-8de9aca023d8, time: 0 hours 0 minutes 25 seconds. Trabant P601 year 1990 VIN: fce81b1e-2916-492a-974a-cac9d623608d, time: 0 hours 0 minutes 50 seconds.
Tento úkol je těžce inspirován tutoriálem od Oracle.
Vytvořte projekt, který bude obsahovat následující třídy:
Bicycle
protected int cadence
protected int speed
protected int gear
public void printDescription()
Bike is in gear 1 with a cadence of 20 and travelling at a speed of 10.
TestBikes
public static void main()
Slovníková definice polymorfismu odkazuje na zásady v biologii, v níž organismus nebo druh může mít mnoho různých forem nebo fáze. Tento princip lze také použít k objektově orientovanému programování a jazyků, tedy i v jazyku Java. Podtřídy třídy mohou definovat své vlastní jedinečné chování a přesto sdílejí některé stejné funkčnosti nadřazené třídy.
Polymorfismus může být demonstrován na třídě Bicycle. Ta obsahuje metodu printDescription(), která vypíše informace o všech datech dané instance.
printDescription()
MountainBike
RoadBike
String suspension
“Front”
“Dual”
int tireWidth
Nyní bychom chtěli, aby printDescription() vypisovalo všechny informace o daném kolu:
Bicycle bike01, bike02, bike03; bike01 = new Bicycle(20, 10, 1); bike02 = new MountainBike(20, 10, 5, "Dual"); bike03 = new RoadBike(40, 20, 8, 23); bike01.printDescription(); bike02.printDescription(); bike03.printDescription();
Bike is in gear 1 with a cadence of 20 and travelling at a speed of 10. Bike is in gear 5 with a cadence of 20 and travelling at a speed of 10. Bike is in gear 8 with a cadence of 40 and travelling at a speed of 20.
Tedy, existují tři třídy: Bicycle, MountainBike a RoadBike. Dvě podtřídy přepisují metodu printDescription() a tisknou jedinečné informace. Jak to, že se volá správná metoda, ačkoliv všechny proměnné jsou typu Bicycle?
Java Virtual Machine (JVM) volá příslušnou metodu pro objekt, na který se odkazuje každá z proměnných. Není to volání metody určené podle typu proměnné. Toto chování se označuje jako volání virtuální metody a ukazuje určitý aspekt důležitých polymorfních rysů v jazyce Java.
Každé kolo bude mít danou barvu, evidujme jen dobře definovaný počet barev výčtovým typem. Výčtovému typu přidejme pro každou barvu též atributy: název barvy a identifikační číslo.
Navrhněte servis kol. Servis přijímá různá kola a může mít různé specializace na opravy. Například může být servis, který se specializuje jen na RoadBike ale zvládne i údržbu běžného kola. Zkusme navrhnout následující 3 servisy:
BasicService
void accept(Bicycle)
“fixing Bicycle”
void accept(MountainBike)
void accept(RoadBike)
“can`t fix ”
MountainBikeService extends BasicService
“fixing MountainBike”
“MountainBikeService can`t fix ”
RoadBikeService extends BasicService
“fixing RoadBike”
“RoadBikeService can`t fix ”
Nyní zkusme zakomponovat do metody main tyto servisy a předejme jim kola.
Servis nám příjímá kola jako Bicycle. Co s tím? Nápady?
Zkusme tedy použít kouzlo, jistě ho oceníte. Nejprve, ale řekněme co je zde za problém. Pokud uděláme toto Bicycle bike = new MountainBike(20, 10, 5, “Dual”); a zavoláme bike.printDescription(); tak se správně zavolá virtuální metoda z MountainBike. Pokud ale zavoláme na mountainBikeService.accept(bike), tak si compiler myslí, že má Bicycle.
Bicycle bike = new MountainBike(20, 10, 5, “Dual”);
bike.printDescription();
mountainBikeService.accept(bike)
Jak na to? Znovu pro pořádek:
Co tedy s tím? Spojme to a udělejme double dispatch. Přidejme metodu visit(BasicService bs) do každého typu kola! Každý typ kola pak zavolá v metodě visit bs.accept(this);. Zopakujme si to:
visit(BasicService bs)
bs.accept(this);
bike.visit(mountainBikeService)
visit
mountainBikeService
this
Tento trik je opět “best practice” a jedná se o návrhový vzor Visitor.
accept
Navrhněte třídu držák, ta bude držet instanci daného typu kola (delegace).
BicycleHolder
MountainBikeHolder extends BicycleHolder
RoadBikeHolder extends BicycleHolder
Nápověda
public class MountainBikeHolder extends BicycleHolder { public MountainBikeHolder(MountainBike bicycle) { super(bicycle); } }
Navrhněte vozidlo Car, které bude přijímat kola různých typů a dle jejich typu bude vybírat vhodný držák, a to podobně jako jako se kola předávala do servisu (v minulém úkolu), tedy metodami:
accept(Bicycle)
accept(MountainBike)
accept(RoadBike)
Kola se ve vozidle budou ukládat jen s pomocí držáku a to do seznamu/listu:
List<BicycleHolder> carHolders = new ArrayList<BicycleHolder>(4);
Generalizujte auto i opravnu přes rozhraní Visitable, upravte kola ať mohou navštívit toto rozhraní. V našem konkrétním případě je kolo visitor (návštěvník) a servis, potažmo auto je visitable (navštěvovaný).
Visitable
public interface BicycleVisitable { public void accept(Bicycle b); public void accept(MountainBike b); public void accept(RoadBike b); }
public class Bicycle { .. public void visit(BicycleVisitable servis) { servis.accept(this); // i v dalsich tridach } }
Řešení otestujme:
System.out.println("Single dispatch:"); Car car1 = new Car(); car1.accept(bike01); car1.accept(bike02); car1.accept(bike03); System.out.println(car1); System.out.println("Double dispatch:"); Car car2 = new Car(); bike01.visit(car2); bike02.visit(car2); bike03.visit(car2); System.out.println(car2);