Celem laboratorium jest zapoznanie się z modelem obiektowym Javy, na przykładzie klasy reprezentującej dwuwymiarowy wektor. Ponadto studenci zapoznają się z frameworkiem do testowania.
Najważniejsze zadania:
- Stworznie klasy
Vector2d
. - Stworzenie klasy
MapDirection
. - Stworzenie klasy
MoveDirection
. - Testy jednostkowe.
- Pola w obiekcie deklarowane są w ciele klasy, np.
class Vector2d {
public int x;
public int y;
}
- Konstruktor jest specjalną metodą w każdej klasie. Nazywa się tak samo jak klasa i nie zwraca wartości. Konstruktor pozwala ustalić początkową wartość pól obiektu, jeśli mają być przekazane przez użytkownika, np.
class Vector2d {
public Vector2d(int x, int y){
this.x = x;
this.y = y;
}
}
- Obiekty klasy tworzy się za pomocą wywołania
new
, np.
Vector2d position1 = new Vector2d(1,2);
- Słowo kluczowe
this
odnosi się do obiektu, na rzecz którego wywołano metodę. Przykładowo w języku C moglibyśmy zdefiniować metodęcreatePoint
:
struct Point {
int x;
int y;
}
struct Point * createPoint(int x, int y){
struct Point * result = malloc(sizeof(struct Point));
result->x = x;
result->y = y;
return result;
}
struct Point * p1 = createPoint(1,2);
Ten kod jest analogiczny do konstruktora, z ta różnicą, że w konstruktorze nie tworzymy obiektu explicite, tylko mamy do
niego dostęp za pomocą słowa kluczowego this
.
- Metoda
equals
ma zwykle taki sam schemat:
public boolean equals(Object other){
if (this == other)
return true;
if (!(other instanceof Vector2d))
return false;
Vector2d that = (Vector2d) other;
// tutaj przeprowadzane jest faktyczne porównanie
}
Należy również wiedzieć, że zmiana metody equals
powinna powodować zmianę metody hashCode
, w przeciwnym razie
umieszczenie obiektów w kolekcji takiej jak Set
będzie niezgodne z semantyką metody equals
.
- Definicję typu wyliczeniowego można rozszerzać dodając do niego pola i metody. Wymaga to umieszczenia średnika po ostatniej wartości typu, np.:
enum MapDirection {
NORTH,
SOUTH,
EAST,
WEST;
public String toString(){
switch(this) {
case NORTH: return "Północ";
case SOUTH: return "Południe";
//...
}
}
}
-
Metody testujące posiadają adnotację
@Test
. -
W metodach testujących można użyć np. następujących asercji:
assertEquals(a, b)
- weryfikuje czy obiektya
ib
są sobie równe (korzystając z metodyequals
),assertTrue(a)
- weryfikuje czy wartość logicznaa
jest prawdą,assertFalse(a)
- weryfikuje czy wartość logicznaa
jest fałszem.
- Projekt z poprzedniego laboratorium należy umieścić w repozytorium git.
- Wersję opracowaną na poprzednich zajęciach należy otagować jako
lab1
oraz wysłać tag do zdalnego repozytorium. - Po zakończeniu pracy nad laboratorium należy je otagować tagiem
lab2
. - Pliki projektu należy umieszczać w pakiecie
agh.ics.oop
. - Wykorzystaj klasę
World
z metodąmain
z poprzednich zajęć. - Utwórz klasę
Vector2d
, która:- posiada dwa publiczne pola
x
iy
typuint
, które nie mogą być modyfikowane (final
), - posiada konstruktor akceptujący parametry
x
iy
, która są przypisywane do pólx
iy
, - posiada metodę
String toString()
, która zamienia pozycję na napis(x,y)
, np. dlax = 1
orazy = 2
, napis ma postać(1,2)
, - posiada metodę
boolean precedes(Vector2d other)
, akceptującą inny obiekt tej klasy i zwracającą wartośćtrue
, jeśli oba pola mają wartość mniejszą bądź równą polom drugiego obiektu, - posiada metodę
boolean follows(Vector2d other)
, akceptującą inny obiekt tej klasy i zwracającą wartośćtrue
, jeśli oba pola mają wartość większą bądź równą polom drugiego obiektu, - posiada metodę
Vector2d add(Vector2d other)
, która zwraca nowy obiekt klasyVector2d
, którego składowe są sumą odpowiednich składowych dodawanych pozycji, - posiada metodę
Vector2d subtract(Vector2d other)
, która zwraca nowy obiekt klasyVector2d
, którego składowe są różnicą odpowiednich składowych odejmowanych pozycji, - posiada metodę
Vector2d upperRight(Vector2d other)
, która akceptuje inny punkt i zwraca obiekt klasyVector2d
posiadający te składowe punktów, które mają większe wartości dla odpowiednich osi (innymi słowy jest prawym górnym rogiem prostokąta, który opisany jest na obu punktach, którego krawędzie są równoległe do osi X i Y), - posiada metodę
Vector2d lowerLeft(Vector2d other)
, która akceptuje inny punkt i zwraca obiekt klasyVector2d
posiadający te składowe punktów, które mają mniejsze wartości dla odpowiednich osi (tzn. lewy dolny róg prostokąta), - posiada metodę
Vector2d opposite()
, która zwraca nowy obiekt tej klasy, posiadający zmienione znaki obu składowych, - posiada metodę
boolean equals(Object other)
która zwraca prawdę, jeśli obie pozycje są sobie równe (zwróć uwagę na typ parametru). Uwaga: zastanów się, jaką inną metodę trzeba dodać po zdefiniowaniu własnegoequals
.
- posiada dwa publiczne pola
- Poniższy obrazek ilustruje metody
precedes
ifollows
.v1
poprzedza (precedes)v2
orazv3
.v2
poprzedzav3
. Wszystkie wektory poprzedzają również same siebie (relacja ta jest zwrotna).v3
następuje po (follows)v2
orazv1
,v2
następuje pov1
. Wszystkie wektory następują również po samych sobie. - Poniższy obrazek ilustruje metody
lowerLeft
orazupperRight
. - W metodzie
main
wprowadź następujący kod:
Vector2d position1 = new Vector2d(1,2);
System.out.println(position1);
Vector2d position2 = new Vector2d(-2,1);
System.out.println(position2);
System.out.println(position1.add(position2));
Sprawdź czy uzyskane wyniki są poprawne.
- Utwórz typ wyliczeniowy
MoveDirection
z czterema kierunkami:FORWARD, BACKWARD, RIGHT, LEFT
. - Utwórz typ wyliczeniowy
MapDirection
z czterema kierunkami:NORTH, SOUTH, WEST, EAST
, który:- posiada metodę
toString
, która dla kierunkuEAST
zwraca łańcuchWschód
, dlaWEST
-Zachód
, itd. - posiada metodę
next
, która dla kierunkuEAST
zwracaSOUTH
(kolejny kierunek zgodnie z ruchem wskazówek zegara), itd. - posiada metodę
previous
, która dla kierunkuEAST
zwracaNORTH
(kolejny kierunek zgodnie z ruchem przeciwnym do ruchu wskazówek zegara), itd. - posiada metodę
toUnitVector
, która zwraca jednostkowy wektor przemieszczenia typuVector2d
zgodny z orientacją na mapie, tzn. dlaNORTH
wektor ten powinien mieć wartość(0,1)
, dlaEAST
(1,0)
, itd.
- posiada metodę
- Sprawdź w metodzie
main
czy metody te działają zgodnie z opisem.
- Zmodyfikuj plik
build.gradle
:- usuń linię
testCompile
w sekcjidependencies
. - dodaj linię
testImplementation("org.junit.jupiter:junit-jupiter:5.8.1")
w tej samej sekcji
- usuń linię
- Utwórz klasę
MapDirectionTest
w katalogusrc/test/java
w pakiecieagh.ics.oop
. - Zaimplementuj test weryfikujący poprawność działania metody
next()
, dla wszystkich przypadków (dodaj anotację@Test
przed deklaracją metody). - Uruchom test korzystając z zielonych trójkątów po lewej stronie.
- Zaimplementuj test weryfikujący poprawność działania metody
previous()
, dla wszystkich przypadków. - Utwórz klasę
Vector2dTest
. - Dodaj testy weryfikujące poprawność metod:
equals(Object other)
,toString()
,precedes(Vector2d other)
,follows(Vector2d other)
,upperRight(Vector2d other)
,lowerLeft(Vector2d other)
,add(Vector2d other)
,subtract(Vector2d other)
,opposite()
.