PDA

View Full Version : سوال: T چیست؟



#root#
پنج شنبه 03 مهر 1393, 06:40 صبح
سلام ، لطفا بگید این T تو این کلاس چیکار میکنه؟ اصلا چیه؟

public class OneOptionDialogFragment<T> extends DialogFragment {

private OnDialogOptionClickListener<T> clickListener;
private T item;

public interface OnDialogOptionClickListener<T extends Object> {
void onDialogOptionPressed(T object);
}

public static <T> OneOptionDialogFragment<T> newInstance(String message){
.
.
.
.
}

}

پیشاپیس سپاسگذارم

ahmad.mo74
پنج شنبه 03 مهر 1393, 08:08 صبح
سلام،

مباحث مربوط به Generics (http://docs.oracle.com/javase/tutorial/extra/generics/index.html) رو مطالعه کنید...

dasssnj
پنج شنبه 03 مهر 1393, 08:37 صبح
همون طور که احمد جان گفتن مربوط به generic ها میشه . حالا منم یه توضیحی میدم :

با generic ها میشه نوع داده های کلاس را هنگام ساخت یه شئ از اون مشخص کرد . مثلا شما اگه با List یا همون ArrayList کا کرده باشی می دونی که زمان تعریف یه شئ از نوع لیست ما مشخص می کنیم که اون لیست چه نوع داده ای را درون خودش نگه داری کنه . مثلا این کد را ببین :

ArrayList<String> mylist = new ArrayList<>();

اینجا ما هنگام تعریف شئ لیستمون مشخص کردیم که این لیست مقادیر String را نگه داری کنه . اونجوری شما هر چی T یا هرچی دیگه اگه اسمش باشه توی کلاس لیست باشن به نوع String تبدیل میشن . توی اون کد خودتونم جا هایی که از T استفاده شده بسته به موقعی که شئ را تعریف می کنید نوع T با اونی که هنگام تعریف می نویسید شناخته میشه.

امیدوارم مطلبو خوب رسونده باشم . دیگه بهتر از این نمی تونستم توضیح بدم.:لبخند:

cups_of_java
پنج شنبه 03 مهر 1393, 11:20 صبح
استفاده از اون نماد واسه اینه که بتونی با یک تایپ کلی (که نمی دونی دقیقن چیه اما می تونی محدودش کنی به یه تایپ های خاص منظور خودت) کار کنی... یعنی کلی دیدن تایپ ها... یا Generics و به خاطر همین کاربردش بهش Parametric Polymorphism هم میگن.
مثال خیلی عینیش نوشتن یه استک هستش. فرض کن میخوای یه کلاس استک بنویسی که کاربر بتونه دیتاش رو توش ذخیره کنه. حالا اگه اون بخواد عدد ذخیره کنه، یا جای دیگه اشیای دانش آموز ذخیره کنه، یا رشته های حرفی ذخیره کنه... تو استکت رو چطوری می نویسی!؟ یعنی ساختار داده درون استکت رو چی میگیری!؟ لیستی از اعداد!؟ یا رشته ها!؟ یا آبجکت های دانش آموز!؟
نباید سه تا کلاس استک واسه ذخیره کردن با هر کدوم از این تایپ ها بنویسی که.... پس میای استکی از T درست میکنی... که T می تونه هر چیزی باشه!

محمد فدوی
پنج شنبه 03 مهر 1393, 11:48 صبح
پاسخ dasssnj و cups_of_java عزیز تا حدودی مطلب رو روشن کرد. منم یه توضیحاتی میدم.
اولا اگه بدونید Generic یعنی کلی/عمومی به فهم مطلب کمک میکنه. در واقع وقتی ما میگیم یه کلاسی بصورت ژنریک تعریف شده یعنی این یه کلاس عمومی/کلی هست! البته باید بدونیم که مبحث ژنریک صرفا به کلاس ها محدود نمیشه و متدها و واسط ها هم میتونن ژنریک باشن.
با یه مثال از پایین به بالا مطلب روشن تر میشه. فرض کنیم که میخوایم یه کلاس بنویسیم که یه آرایه از String رو ازمون تحویل بگیره و یه متد هم داره برای جستجو که اون متد مقدار String رو میگیره و اگه معادلش توی آرایه چیزی بود اندیس اون رو برمیگردونه. در غیر اینصورت مقدار ۱- رو برمیگردونه.
خب کلاس رو بنویسیم:

public class StringWalker {
private String[] array;

public StringWalker(String[] array) { this.array = array; }

public int find(String str) {
for(int i = 0; i < array.length; i++)
if(array[i].equals(str)) {
return i;
}
return -1;
}
}

خب کلاس خوبی نوشتیم! اما بیاید یه کلاسم واسه Integerها بنویسیم! :اشتباه: با چندتا تغییر نام اینو مینویسیم:



public class IntegerWalker {
private Integer[] array;

public StringWalker(Integer[] array) { this.array = array; }

public int find(Integer integer) {
for(int i = 0; i < array.length; i++)
if(array[i].equals(integer)) {
return i;
}
return -1;
}
}


در مورد کلاس های دیگه چی؟! بازم بنویسیم؟! بهتره یه راهی پیدا کنیم تا کلاسمون با انواع مختلف کار کنه و اصطلاحا چند ریختی باشه! اینجا دوتا راه داریم:
۱. کلاس ObjectWalker رو بنویسیم (که قبلا که جاوا ژنریک نداشت راه مناسبی بود!) ولی اونوقت هم اولا برناممون از نظر شئ گرایی خوش ریخت نیست و در ضمن باید همیشه آرایه رو از نوع Object بش پاس کنیم.
۲. راه بهتر استفاده از ژنریک هست. کلاس Walker رو به اینصورت تعریف میکنیم:



public class Walker <U> {
private U[] array;

public Walker(U[] array) { this.array = array; }

public int find(U target) {
for(int i = 0; i < array.length; i++)
if(array[i].equals(target))
return i;
return -1;
}
}


فکر میکنم تاحدودی بشه فهمید چه اتفاقی افتاد! حالا این کلاس ما با هرنوعی از داده قابلیت کار داره. البته توجه داشته باش که ژنریک فقط در مورد کلاس ها معنی داره و نه انواع پایه مثل int و float و ... برای انواع پایه باید از کلاس های معادلشون یعنی Integer، Float و ... استفاده کنیم.
* از قصد اسم نوع ژنریک رو U گذاشتم که فکر نکنی همیشه باید T باشه! :بامزه: ولی رسم بر اینه که از T استفاده بشه.

طرز استفاده:

Walker<Double> doubleWalker = new Walker<>(new Double[] { 2.3, 5.324, 7.96, 3.14, 8.06, 2.71 });
System.out.println(doubleWalker.find(3.14));



حالا به عنوان آخرین مطلب شاید یکی بیاد بگه حالا همیشه باید برای ژنریک کردن کدمون از کلاس استفاده کنیم؟! نمیشه تابع find رو بصورت static تعریف کنیم و اونم بتونه هرنوع داده ای رو بگیره؟! کار نشد نداره!


public class Walker {
public <U> static int find(U[] array, U target) {
for(int i = 0; i < array.length; i++)
if(array[i].equals(target))
return i;
return -1;
}
}

طرز استفاده:


String[] stringArray = {"Zero", "One", "Two", "Three", "Four"};
int index = Walker.<String>find(stringArray, "Two");


دیگه با این اوصاف لازم نبود کلاسمون متغیر ژنریک داشته باشه. چند تا مطلب می مونه که من فقط اینجا طرحشون میکنم و از dasssnj عزیز هم خواهش میکنم توی آموزش هایی که داره قرار میده در این مورد هم حرف بزنه:
۱. نمیشه یه کلاس/متد ژنریک چندتا متغیر ژنریک داشته باشه؟
۲. نمیشه متغیر ژنریک رو محدود کرد تا مثلا فقط کلاسهایی رو قبول کنه که واسط Cloneable رو پیاده سازی کردن؟
۳. نمیشه یه کلاس ژنریک یک یا چند متد ژنریک داشته باشه؟
۴. واسط های ژنریک به چه دردی میخورن؟
۵. قابلیت های جدید اضافه شده در جاوا در مورد‌ ژنریک!؟
۶. عبارات لاندا چی هستن؟! ربطی به ژنریک دارن؟!
۷. و ...

موفق باشی.

dasssnj
پنج شنبه 03 مهر 1393, 12:19 عصر
من دارم از پایه شروع می کنم تا برسم به این آموزشا کلی وقت میبره.
ولی هر وقت احساس کردم نیازه حتما آموزششو می زارم.
ضمنا جواب سوال 5 را نمی دونم و همین طور قسمت دوم سوال ششم.:لبخند:

محمد فدوی
پنج شنبه 03 مهر 1393, 13:07 عصر
:قهقهه: خب حالا تا آموزشایی که داری میذاری به مبحث ژنریک برسی شاید طول بکشه ولی واقعا توی همه ی زبون ها(توی #C و ++C هم این قضیه خیلی شایعه) خیلی از افراد دید درستی ندارن از این مبحث. اگه آموزشش رو بذاری به خیلیا کمک میکنه.

#root#
پنج شنبه 03 مهر 1393, 16:48 عصر
بعضی مباحث هست مثل این مورد اصلا با منابع غیر فارسی نمیتونم درکشون کنم ، گرچه به مثال یه چیزایی دستگیر آدم میشه ;
از همه دوستان ممنونم ، بخصوص از MohamadF (http://barnamenevis.org/member.php?145812-MohamadF) که شرمنده کردن واقعا :قلب: یعنی بهتر از این نمیشد :)

یه سوال پیشومد برام ، تو این مثالی که زدین از متد equals استفاده کردین و این متد مگه فقط برا رشته ها نیست؟ مگه نباید اعداد صحیح با == مقایسه بشن؟ پس چرا الان با هر نوع داده ای جوابش صحیحه؟

ahmad.mo74
پنج شنبه 03 مهر 1393, 17:14 عصر
متد equals توی کلاس Object تعریف شده به این صورت:


public boolean equals(Object obj) {
return (this == obj);
}


که بای دیفالت به همه کلاس ها ارث میرسه، اما خب میشه هر جوری که دوست داشتیم اوررادیش کنیم، مثلا تو کلاس String اینجوری اورراید شده:


public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}


شما هم میتونی هر جوری که میخوای اوررایدش کنی، مثلا:


public class Walker<E> {


private E array[];
private int id;


public Walker(E[] array) {
this.array = array;
}


public static void main(String[] args) {
Walker<String> stringWalker = new Walker<>(new String[]{"a", "b", "c"});
stringWalker.setId(1);
Walker<Integer> integerWalker = new Walker<>(new Integer[]{1, 2, 3});
integerWalker.setId(1);
System.out.println(stringWalker.equals(integerWalk er));
}


public E find(E target) {
for (E e : array) {
if (e.equals(target)) {
return e;
}
}
return null;
}


public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}


@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Walker))
return false;
Walker other = (Walker) obj;
return id == other.id;
}


}



Output : true


یه نکته ای رو هم بگم اینجا که توی متد find از equals استفاده کردیم بستگی به نوعی که واسش تعیین کردیم داره یعنی اگر <Walker<String باشه متد equals کلاس String اجرا میشه و...