بخشی از پاورپوینت
اسلاید 1 :
انواع داده عام Generics
دوره برنامهنويسی جاوا
اسلاید 2 :
حقوق مؤلف
کلیه حقوق این اثر متعلق به انجمن جاواکاپ است
بازنشر یا تدریس آنچه توسط جاواکاپ و به صورت عمومی منتشر شده است، با ذکر مرجع (جاواکاپ) بلامانع است
اگر این اثر توسط جاواکاپ به صورت عمومی منتشر نشده است و به صورت اختصاصی در اختیار شما یا شرکت شما قرار گرفته، بازنشر آن مجاز نیست
تغییر محتوای این اثر بدون اطلاع و تأیید انجمن جاواکاپ مجاز نیست
اسلاید 3 :
سرفصل مطالب
کلاسهای عام (Generic Classes)
متدهای عام (Generic Methods)
انواع عام و وراثت
فرایند مَحو (Erasure)
اسلاید 4 :
چه نیازی به انواع عام است؟
اسلاید 5 :
انواع داده عام (Generic)
گاهی منطق پیادهسازی یک کلاس، برای انواع داده مختلف یکسان است
مثلاً منطق متد add در کلاس ArrayList به ازای لیستی از رشته یا عدد متفاوت نیست
راه اول: به ازای هر نوع داده، یک کلاس ArrayList بسازیم
مثلاً: StringArrayList و IntegerArrayList و StudentArrayList
این کلاسها مشابه (کپی) یکدیگرند
راه دوم: یک کلاس ArrayList تعریف کنیم و درهنگام استفاده نوع آن را محدود کنیم
کلاس ArrayList یک نوع داده عام (Generic) است
بحث این جلسه: چگونه کلاسهای عام (مثل ArrayList) تعریف کنیم؟
ArrayList list1 = new ArrayList();
list1.add("Ali");
ArrayList list2 = new ArrayList();
list2.add(new Integer(2));
Code redundancy
اسلاید 6 :
مسأله چیست؟
فرض کنید میخواهیم کلاس «ظرفی از اشیاء» طراحی کنیم
مثلاً یک لیست یا مجموعه یا پشته یا صف
این کلاس متدهایی مثل add و delete خواهد داشت. مثال:
اما معمولاً هر ظرف شامل اشیائی از یک نوع یکسان است
مثلاً لیستی از «رشته»ها یا مجموعهای از «عدد»ها یا یک صف از «دانشجو»ها
چنین نیازی را چگونه پیاده میکنید؟ مثلاً متد add چگونه اعلان شود؟
مثلاً این تعریف مناسب است؟
MyList q = new MyList();
q.add("Ali");
q.add("Taghi");
void add(Object obj) {.}
اسلاید 7 :
مسأله چیست؟ (ادامه)
فرض کنید میخواهیم کلاس MyList یا ArrayList را تعریف کنیم
متد add را چگونه تعریف کنیم؟
اگر این متد اینگونه باشد:
این کلاس فقط برای رشتهها کار خواهد کرد (لیستی از رشتهها)
اگر این متد اینگونه باشد:
نوع اشیاء این کلاس محدودیتی ندارد (لیستی از هر نوع شیء)
ممکن است در یک لیست، همزمان اشیائی از نوع رشته، عدد یا دانشجو داشته باشیم
معمولاً علاقمندیم یک ظرف (مثلاً لیست) ، اشیائی از یک نوع داشته باشد
مثل ظرفهای جاوا (ArrayList، HashSet و .) : این ظرفها چگونه تعریف شدهاند؟
void add(String obj) {.}
void add(Object obj) {.}
اسلاید 8 :
تعریف انواع داده عام
اسلاید 9 :
public class Stack {
private E[] elements;
private int top;
public void push(E pushValue) {
if (top == elements.length - 1) throw new FullStackException();
elements[++top] = pushValue;
}
public E pop() {
if (top == -1) throw new EmptyStackException();
return elements[top--];
}
public Stack(int maxsize) {
top = -1;
elements = (E[]) new Object[maxsize];
}
}
نحوه تعریف کلاس عام
Stack st1;
st1 = new Stack(10);
st1.push("A");
st1.push("B");
String p1 = st1.pop();
Stack st2;
st2 = new Stack(10);
st2.push(new Integer(1));
st2.push(new Integer(2));
Integer p2 = st2.pop();
st2.push("A");
پارامتر نوع (Type Parameter)
اسلاید 10 :
فرض کنید میخواهیم کلاس Pair تعریف کنیم
هر شیء از این کلاس یک جفت شیء (زوج مرتب) در درون خود نگه میدارد
میخواهیم در زمان ایجاد شیء (و نه در زمان تعریف کلاس) نوع این دو شیء را تعیین کنیم
Pair p1;
p1 = new Pair("Ali", 19.0);
String name = p1.getFirst();
Double avg = p1.getSecond();
Pair p2;
p2 = new Pair("Ali", "Alavi");
String fname = p2.getFirst();
String lname = p2.getSecond();
public class Pair {
private T1 first;
private T2 second;
public T1 getFirst() {return first;}
public void setFirst(T1 first) {this.first = first;}
public T2 getSecond() {return second;}
public void setSecond(T2 second) {this.second = second;}
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
}
مثال: کلاس Pair
اسلاید 11 :
مثال
برای هر گره از یک لیست پیوندی، میخواهیم یک کلاس با نام Node تعریف شود
هر گره دو فیلد مهم دارد:
1- مقدار (از هر نوعی میتواند باشد)
2- ارجاع به گره بعدی (ارجاعی به یک Node)
class Node {
E item;
Node next;
Node(E element, Node next) {
this.item = element;
this.next = next;
}
}
Node last = new Node("Taghi", null);
Node first = new Node("Ali", last);
اسلاید 12 :
مرور چند واسط و کلاس عام جاوا
اسلاید 13 :
مثال
class ArrayList implements List
//extends. implements.
{
public int size() {.}
public E get(int index) {.}
public E set(int index, E element) {.}
public boolean add(E e) {.}
.
}
interface List extends Collection {
int size();
boolean isEmpty();
boolean add(E e);
boolean equals(Object o);
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
List subList(int fromIndex, int toIndex);
}
مانند یک کلاس، یک واسط یا یک کلاس مجرد هم میتواند عام (generic) باشد
اسلاید 14 :
مثال
interface Map {
int size();
V get(Object key);
V put(K key, V value);
V remove(Object key);
Set keySet();
Collection values();
}
public class HashMap implements Map
//extends. implements.
{
.
}
امکان استفاده از چند «پارامتر نوع» در یک کلاس عام (generic type)
اسلاید 15 :
چند نکته درباره انواع داده عام
اسلاید 16 :
نکته
هنگام تعریف متغیر از یک نوع عام، میتوانیم نوع عام را با یک نوع مشخص تعیین کنیم
مثلاً واسط List را در نظر بگیرید:
هنگام ایجاد متغیر از جنس List ، میتوانیم E را با نوع موردنظر جایگزین کنیم:
اما به عنوان «پارامتر نوع»، نمیتوانیم از انواع داده اولیه (مثل double) استفاده کنیم
جایگزین E در مثال فوق فقط یک «کلاس» میتواند باشد
خطای کامپایل:
interface List
List strs;
List ints;
List stus;
List error1;
List error2;
اسلاید 17 :
فایده انواع داده عام
در زمان کامپایل، از اشتباه برنامهنویس جلوگیری میکند (پیش از اجرای برنامه)
اگر برنامهنویس متغیر strs را به این شکل تعریف کند:یعنی قرار است strs لیستی از رشتهها باشد
با ذکر پارامتر نوع (رشته) و نظارت کامپایلر، برنامه نویس نمیتواند سهواً اشتباه کند
مثلاً برنامهنویس نمیتواند strs.add(new Integer(5)) را فراخوانی کند
زیرا کامپایلر با یک syntax error جلوی آن را میگیرد
به نوع عام (Generic Type) نوع پارامتردار (Parameterized Types) هم میگویند
در مثال فوق، List یک نوع عام یا پارامتردار است: String به عنوان پارامتر نوع
نکته: داده عام از نسخه 5 به جاوا اضافه شد. قبل از JDK1.5 اصلاً Generic نداشتیم
List strs;
اسلاید 18 :
محدود کردن نوع عام
هنگام استفاده از یک نوع عام، از هر کلاسی به عنوان پارامتر نوع میتوانیم استفاده کنیم
ولی گاهی نیازمندیم که پارامتر نوع را محدود به انواع خاصی کنیم
مثال:
در اینجا، extends یعنی «پارامتر نوع» باید زیرکلاس یا زیرواسط نوع مشخصشده باشد
مثال: فرض کنید:
class NumbersQueue{.}
inetrface SortedList{.}
NumbersQueue n;
NumbersQueue d;
NumbersQueue s;
NumbersQueue p;
class Person{}
SortedList l;
SortedList f;
SortedList s;
SortedList p;
اسلاید 19 :
نوع خام (Raw Type)
انواع داده عام را بدون تصریح «پارامتر نوع» هم میتوان استفاده کرد
در این صورت، کامپایلر حداقلِ محدودیت ممکن را برای این انواع اعمال میکند
در این مثال، هر شیئی قابل افزودنبه List است (محدودیتی نیست)
در این مثال، فقط اشیائی از نوع Number (یا فرزندان Number)قابل استفاده در queue هستند
ArrayList list = new ArrayList();
list.add("A");
list.add(new Integer(5));
list.add(new Character('#'));
class NumbersQueue{
public void enqueue(T o){}
public T dequeue(){.}
}
NumbersQueue queue;
queue = new NumbersQueue();
queue.enqueue(new Integer(1));
queue.enqueue(new Double(3.14));
queue.enqueue("Ali");
اسلاید 20 :
نکته
از نسخه 7 (java 1.7) به بعد، «استنتاج نوع» برای انواع عام ممکن شده است
Type Inference
بهويژه، ذکر نوع عام در هنگام نمونهسازی از انواع عام لازم نیست (نوع آن استنتاج میشود)
به این امکان، عملگر لوزی (diamond operator) میگویند
مثال:
ArrayList list = new ArrayList();
ArrayList list = new ArrayList<>();
Map> map = new HashMap>();
Map> map = new HashMap<>();
قدیمی
جدید
قدیمی
جدید