You are on page 1of 59

ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Напредно
програмирање
Предавање 4
Генеричко програмирање
Вон. проф. д-р Ѓорѓи Маџаров
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Мотивација - Исклучок при кастирање


public class OldBox {
Object data;
public OldBox(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
}
OldBox intBox = new OldBox(42);
int x = (Integer) intBox.getData();
OldBox strBox = new OldBox(“Hi”);
String s = (String) strBox.getData();
Мора да се направи експлицитно кастирање, во
спротивно имаме грешка при компјалирање
int y = (Integer) strBox.getData();
intBox = strBox;
ClassCastException!
Се компајлира но паѓа при извршување
НАПРЕДНО ПРОГРАМИРАЊЕ 2
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

public class IntBox { public class StrBox {


Integer data; String data;
public IntBox(Integer data) { public StrBox(String data) {
this.data = data; this.data = data;
} }
public Integer getData() { public String getData() {
return data; return data;
} }
} }
IntBox intBox = new IntBox(42); public class FooBox {
int x = intBox.getData(); Foo data;
public FooBox(Foo data) {
StrBox strBox = new StrBox(“Hi”); this.data = data;
String s = strBox.getData(); }
int y = (Integer) strBox.getData(); public Foo getData() {
intBox = strBox; return data;
}
Грешки фатени од компајлерот }
Бесконечно многу можни класи

НАПРЕДНО ПРОГРАМИРАЊЕ 3
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Праќање на параметри во методи: Аналогија


public abstract class Sum { public abstract class NewSum {
public static int sum_0_1() { public static int
return (0+1); sum(int m, int n) {
} return (m+n);
… }
public static int sum_15_22() { }
return (15+22);
}
… Методите примаат параметри
}

public class Main { public class NewMain {


public static void public static void
main(String[] nu) { main(String[] nu) {
int j = Sum.sum_0_1(); int j = NewSum.sum(0,1);
… …
int k = Sum.sum_15_22(); int k = NewSum.sum(15,22);
} }
} }
Лошо – бесконечно многу методи Праќање параметри на методите
НАПРЕДНО ПРОГРАМИРАЊЕ 4
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Java генерици: клучна идеја


 Дефиниции со параметризирани типови
 Параметризирани класи и методи
 Обезбедување на безбедност на тип
 Компајлерот обезбедува проверка на тип
 Превенција на грешки настанати како
резултат на кастирање при извршување на
програмата

НАПРЕДНО ПРОГРАМИРАЊЕ 5
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички класи
public class OldBox { public class Box<E> {
Object data; E data;
public OldBox(Object data) { public Box(E data) {
this.data = data; this.data = data;
} }
public Object getData() { public E getData() {
return data; return data;
} }
} }

Сакаме box да содржи „специфична“ E се однесува на конкретен тип


класа – апстрактно репрезентирана
Конструкторот зема објект од тип E, не
Object не функционира како што било кој објект
видовме во претходните примери
За да се користи класата, E мора да се
Решение – параметризирање на замени со конкретна класа
дефиницијата на класата
НАПРЕДНО ПРОГРАМИРАЊЕ 6
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Како се користи генеричка класа

public class Box<E> { Box<Integer> intBox =


E data; new Box<Integer>(42);
public Box(E data) { int x = intBox.getData();//no cast needed
this.data = data;
}
Box<String> strBox =
public E getData() {
return data; new Box<String>(“Hi”);
} String s = strBox.getData();//no cast needed
}
Следните наредби неможат да се компајлираат:

String s = (String) intBox.getData();


int y = (Integer) strBox.getData();
intBox = strBox;

Грешките при извршување станаа грешки при


компајлирање

НАПРЕДНО ПРОГРАМИРАЊЕ 7
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерици
 Дефиницијата на класата со параметарски
типови се зачувува во датотека и компајлира
исто како и секоја друга класа
 Еднаш компајлирана генеричка класа може
да се употребува како секоја друга класа
 Како и да е, типот на класата на параметарскиот
тип мора да се специфицира пред да се користи
во програма
 Ова се нарекува инстанцирање на генеричка
класа
Sample<String> object =
new Sample<String>();

НАПРЕДНО ПРОГРАМИРАЊЕ 8
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Дефиниција на класа со
параметарски тип

НАПРЕДНО ПРОГРАМИРАЊЕ 9
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Дефиниција на класа со
параметарски тип
 Класата која е дефинирана со параметар
како тип се нарекува генеричка класа или
параметризирана класа
 Параметарскиот тип се дава во аглести загради по
името на класата во нејзиното заглавие
 Секоја не-клучен збор може да биде употребен
како идентификатор за параметарски тип
 По конвенција параметарот стартува со голема
буква
 Параметарскиот тип може да се употребува како и
секој друг тип во дефиницијата на класата

НАПРЕДНО ПРОГРАМИРАЊЕ 10
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генеричка Pair Класа (1 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 11
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генеричка Pair Класа (2 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 12
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генеричка Pair Класа (3 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 13
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генеричка Pair Класа (4 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 14
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата (1 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 15
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата (2 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 16
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата (3 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 17
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Името на генеричкиот конструктор нема


параметарски тип
 Иако името на класата кај генеричка класа го содржи и
параметарскиот тип, сепак параметарскиот тип не се користи во
заглавието на дефиницијата на конструкторот
public Pair<T>()
 Конструкторот може да користи параметарски тип како тип на
параметар, но во овој случај, аглестите загради не се користат
public Pair(T first, T second)
 Кога се инстанцира објект од генеричка класа се
користат аглестите загради
Pair<String> pair =
new Pair<String>("Happy", "Day");
Pair<String> pair =
new Pair<>("Happy", "Day"); Инференција на типови
The diamond
Pair<String> pair =
new Pair("Happy", "Day"); Raw тип

НАПРЕДНО ПРОГРАМИРАЊЕ 18
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Raw тип
 Raw тип е името на генеричката класа или интерфејс
без било каков тип на аргументи.
public class Box<T> { public void set(T t)
{ /* ... */ } // ... }
 За да се креира параметризиран тип од Box<T>
треба да се даде конкретен тип за формалниот
параметарски тип T:
Box<Integer> intBox = new Box<>();
 Ако конкретниот тип се изостави, се креира raw тип
од Box<T>:
Box rawBox = new Box();
 Box е raw тип на генеричкиот тип Box<T>. Не-
генеричка класа или интерфејс тип не е raw тип.
НАПРЕДНО ПРОГРАМИРАЊЕ 19
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Raw тип
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK

Box rawBox = new Box(); // rawBox is a raw type of


Box<T>
Box<Integer> intBox = rawBox; // warning: unchecked
conversion

Box<String> stringBox = new Box<>();


Box rawBox = stringBox; rawBox.set(8); // warning:
unchecked invocation to set(T)

НАПРЕДНО ПРОГРАМИРАЊЕ 20
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Примитивните типови не можат да се


користат како параметарски типови

 Типот на податоците кои се користат како


параметарски типови секогаш мораат да
бидат референца типови (reference type)
 Не можат да бидат примитивни типови како int,
double, или char
 БидејќиJava има automatic boxing, ова не
претставува голема рестрикција
 Забелешка: референца типовите вклучуваат
полиња

НАПРЕДНО ПРОГРАМИРАЊЕ 21
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Параметарскиот тип не може да се


употребува секаде
 Во дефиниција на параметризирана класа,
постојат места каде име на обична класа
може да се користи, но не е дозволено
користење на параметарскиот тип
 Конкретно, параметарскиот тип не може да се
користи во едноставна операција со new
операторот за креирање на објект
 Параметарскиот тип не може да се користи како
име на конструктор или како конструктор:
T object = new T();
T[] a = new T[10];
T[] a = new (T[])Object[10];
НАПРЕДНО ПРОГРАМИРАЊЕ 22
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Инстанца на генеричка класа не може да


биде основен тип на поле
 Полиња дефинирани на следниот начин
се нелегални:
Pair<String>[] a =
new Pair<String>[10];
 Иако ова делува разумно, сепак тоа не е
дозволено со генериците во Java

НАПРЕДНО ПРОГРАМИРАЊЕ 23
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата и


automatic boxing (1 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 24
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата и


automatic boxing (2 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 25
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на Pair класата и


automatic boxing (3 од 3)

НАПРЕДНО ПРОГРАМИРАЊЕ 26
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Дефиниција на класа може да има повеќе


од еден параметарски тип
 Дефиниција на генеричка класа може
да има произволен број на параметрски
типови
 Параметарските типови се листаат во
аглести загради, одделени со запирка

НАПРЕДНО ПРОГРАМИРАЊЕ 27
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Повеќе параметарски типови (1 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 28
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Повеќе параметарски типови (2 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 29
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Повеќе параметарски типови (3 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 30
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Повеќе параметарски типови (4 од 4)

НАПРЕДНО ПРОГРАМИРАЊЕ 31
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на генеричка класа со


два параметарски типа (1 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 32
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на генеричка класа со


два параметарски типа (1 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 33
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генеричка класа не може да биде


класа исклучок

 Не е дозволено креирање на генеричка класа


од Exception, Error, Throwable, или било
која изведена класа од Throwable
 не може да се креира генеричка класа чии објекти
се throwable
public class GEx<T> extends Exception
 Претходниот пример ќе јави грешка при
компајлирање

НАПРЕДНО ПРОГРАМИРАЊЕ 34
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички интерфејси
 Интерфејс може да има еден или
повеќе параметарски типови
 Деталите и нотацијата е иста како и
класите со параметарски типови

НАПРЕДНО ПРОГРАМИРАЊЕ 35
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички методи
 Параметарскиот тип може да се користи кај
методите од генеричка класа
 Како дополнување, генеричкиот метод може
да има свој параметарски тип, различен од
оној на класата
 Генерички метод може да биде член на обична
или на генеричка класа и да има свој
параметарски тип
 Параметарскиот тип на генеричкиот метод е
локален и важи за самиот метод, не и за класата

НАПРЕДНО ПРОГРАМИРАЊЕ 36
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички методи
 Параметарскиот тип мора за се зададе (во
аглести загради) по сите модификатори и
пред типот на повратниот податок
public static <T> T genMethod(T[] a)
 Кога еден од овие генерички методи се
повикува, пред името на методот во аглести
загради се поставува конкретниот податочен
тип
String s = NonG.<String>genMethod(c);

НАПРЕДНО ПРОГРАМИРАЊЕ 37
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички методи
Consider the following class: public class Bar<T> {
public class Foo { //Bar is parameterized
//Foo is not parameterized public T aMethod(T x) {
public <T> T aMethod(T x) { return x;
//will not compile without <T> }
//to indicate that this is a public static void
//parameterized method. main(String[] args) {
return x; Bar<Integer> bar =
} new Bar<Integer>();
public static void int k = bar.aMethod(5);
main(String[] args) { String s = bar.aMethod("abc");
Foo foo = new Foo(); //Compilation error here
int k = foo.aMethod(5); }
String s = foo.aMethod("abc"); }
}
}
Фиксна foo класа и променливи Објектот Bar<T> е фиксиран и ние
параметри на aMethod() сме врзани со конкретно T.

НАПРЕДНО ПРОГРАМИРАЊЕ 38
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на генерички методи


 Обезбедување на безбедност на типови
кај методи кои оперираат со различни
типови
 Типот кој се враќа зависи од влезниот тип

НАПРЕДНО ПРОГРАМИРАЊЕ 39
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерички класи во методи


Параметризирана класа е тип како и секоја друга класа
Може да се користи во методи како влезен тип (на податок) или тип
кој се враќа:
Box<String> aMethod(int i, Box<Integer> b) { … }

Ако класата е параметризирана, типот на параметарот може да се


користи како тип на податок при декларација:

public class Box<E> {


E data;
public Box(E data) {
this.data = data;
}
public E getData() {
return data;
}
public void copyFrom(Box<E> b) {
this.data = b.getData();
}
}//We have added an infinite number of types of Boxes
//by writing a single class definition

НАПРЕДНО ПРОГРАМИРАЊЕ 40
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Изведување на генерички класи


 Генеричка класа може да биде дефинирана
како изведена класа од обична класа или
друга генеричка класа
 Како и кај обичните класи, објект од тип на
изведена класа го има и типот на супер класата
 За дадени две класи: A и B, и генеричка класа
G
 Не постои врска меѓу G<A> и G<B>

НАПРЕДНО ПРОГРАМИРАЊЕ 41
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Изведени генерички класи (1 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 42
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Изведени генерички класи (2 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 43
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на изведени генерички


класи (1 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 44
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Користење на изведени генерички


класи (2 од 2)

НАПРЕДНО ПРОГРАМИРАЊЕ 45
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Ограничувања на параметарските типови


 Понекогаш има смисла да се ограничат
можните типови кои можат да се користат
како замена на параметарот T
 На пример, за да се обезбеди користење на класи
кои го имплементираат Comparable интерфејсот,
параметарската класа се дефинира на следниот
начин:
public class RClass<T extends Comparable>
 "extends Comparable" служи како граница на
параметарскиот тип T
 При обид да се постави на местото на T тип кој не го
имплементира Comparable интерфејсот ќе резултира во
грешка при компајлирање

НАПРЕДНО ПРОГРАМИРАЊЕ 46
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Ограничувања на параметарските типови


 Граница на типот може да биде класа или интерфејс
 Само изведени класи можат да се користат на местото на
параметарските типови
public class ExClass<T extends Class1>
 Во изразот можат да се користат повеќе интерфејси
и максимум една класа
 Ако постои повеќе од еден параметарски тип,
синтаксата е следна:
public class Two<T1 extends Class1, T2 extends
Class2 & Comparable>

НАПРЕДНО ПРОГРАМИРАЊЕ 47
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Ограничувања на параметарските типови

НАПРЕДНО ПРОГРАМИРАЊЕ 48
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Ограничувања на параметарските
типови
public class MathBox<E extends Number> extends Box<Number> {
public MathBox(E data) {
super(data);
}
public double sqrt() {
return Math.sqrt(getData().doubleValue());
}
}
<E extends Number> значи дека параметарскиот тип на MathBox мора да
биде под-класа на Number класата.

new MathBox<Integer>(5);//Legal
new MathBox<Double>(32.1);//Legal
new MathBox<String>(“No good!”);//Illegal

НАПРЕДНО ПРОГРАМИРАЊЕ 49
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Ограничувања на параметарските
типови
Во дефиницијата на параметризирана класа, параметарскиот тип е валиден
податочен тип:

public class OuterClass<T> {


private class InnerClass<E extends T> {

}

}

НАПРЕДНО ПРОГРАМИРАЊЕ 50
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерици и subtyping
Иако следнава наредба се чини разумна сепак компајлерот дава
порака за грешка:
Box<Number> numBox = new Box<Integer>(31);

НАПРЕДНО ПРОГРАМИРАЊЕ 51
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Генерици и subtyping
 Пораката за грешка која ја дава компајлерот е “Incompatible Type”
 numBox може да содржи само објект од Number а не објект од тип
Integer (иако Integer е класа изведена од Number

 Box<T> не е класа изведена од Box<E> дури и ако T е изведена од


класа од класата E

//Consider the following lines of code


Box<String> strBox = new Box<String>(“Hi”);//1
Box<Object> objBox = strBox;//2 – compilation error
objBox.setData(new Object());//3
String s = strBox.getData();//4–an Object to a String!

НАПРЕДНО ПРОГРАМИРАЊЕ 52
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери без ограничување


Користење на џокери без ограничување за секој тип на параметар
<?> се користи за да се специфицира џокер без ограничување.
Следните наредби се легални
Box<?> b1 = new Box<Integer>(31);
Box<?> b2 = new Box<String>(“Hi”);
b1 = b2;

Препознавање на џокер (Wildcard capture):


Компајлерот може да препознае кој е типот на b1 преку десната страна на
операторот за доделување

НАПРЕДНО ПРОГРАМИРАЊЕ 53
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери без ограничување


Сакаме да напишеме метод за печатење на било кој Box.
public static void printBox(Box<Object> b) {
System.out.println(b.getData());
}

Box<String> strBox = new Box<String>(“Hi”);


printBox(strBox);//compilation error

public static <T> void printBox(Box<T> b) {


System.out.println(b.getData());
}//parameterized method

public static void printBox(Box<?> b) {


System.out.println(b.getData());
}//using unbounded wildcard
НАПРЕДНО ПРОГРАМИРАЊЕ 54
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери без ограничување


Box<?> е родител класа на Box<T> за секое T.

Box<?>

Box<Integer> Box<String> Box<Object>

Џокери без ограничување се корисни кога се пишува код


кој е комплетно независен од параметарскиот тип

НАПРЕДНО ПРОГРАМИРАЊЕ 55
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери со ограничување од горе


“Box од било кој тип кој е пот-тип на Number”.

Box<? extends Number>

Box<Number> Box<Integer> Box<Double>

Box<? extends Number> numBox = new Box<Integer>(31);

<? extends E> се нарекува “upper bounded wildcard (џокер


со ограничување од горе)” затоа што дефинира тип кој е
ограничен од (супер) класата E.
НАПРЕДНО ПРОГРАМИРАЊЕ 56
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери со ограничување од горе


public class Box<E> {
public void copyFrom(Box<E> b) {
this.data = b.getData();
}
}
//We have seen this earlier
//We can rewrite copyFrom() so that it can take a box
//that contains data that is a subclass of E and
//store it to a Box<E> object
public class Box<E> {
public void copyFrom(Box<? extends E> b) {
this.data = b.getData();//b.getData() is a
//subclass of this.data
}
}
Box<Integer> intBox = new Box<Integer>(31);
Box<Number> numBox = new Box<Number>();
numBox.copyFrom(intBox);

НАПРЕДНО ПРОГРАМИРАЊЕ 57
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери со ограничување од долу


“Box од било кој тип кој е супер-тип на Integer”.

Box<? super Integer>

Box<Number> Box<Integer> Box<Object>

<? super E> се нарекува “lower bounded wildcard (џокер со


ограничување од долу)” затоа што дефинира тип кој е ограничен од
(под) класата E.

НАПРЕДНО ПРОГРАМИРАЊЕ 58
ФАКУЛТЕТ ЗА ИНФОРМАТИЧКИ НАУКИ
И КОМПЈУТЕРСКО ИНЖЕНЕРСТВО

Џокери со ограничување од долу


Да претпоставиме дека методот copyTo() ги копира податоците во спротивна
насока од методот copyFrom().
copyTo() ги копира податоците од матичниот објект во објектот пратен како
аргумент
public void copyTo(Box<E> b) {
b.data = this.getData();
}

Претходниот код е легален и регуларен се додека матичниот објект и објектот


b се box од истиот тип
Но b може да биде box од објекти инстанцирани од супер-класа на E.
public void copyTo(Box<? super E> b) {
b.data = this.getData();
//b.data() is a superclass of this.data()
}
Box<Integer> intBox = new Box<Integer>(31);
Box<Number> numBox = new Box<Number>();
intBox.copyTo(numBox);
НАПРЕДНО ПРОГРАМИРАЊЕ 59

You might also like