استارت‌آپ و کارآفرینی

آموزش قدم به قدم جاوا – قسمت بیست و چهارم – بخش دوم

متدهای جنریک (Generic Methods)

همانگونه که می‌توانستیم کلاس‌ها را به صورت جنریک تعریف کنیم متدها را نیز می‌توانیم به صورت جنریک بنویسیم. متدهای جنریک می‌توانند نوع داده پارامترهای خود را به عنوان یک پارامتر جنریک دریافت کنند. متدهای جنریک را هم در کلاس‌های جنریک و هم در کلاس‌های غیر جنریک می‌توان تعریف کرد.

مثال:

public <E> void arrayToArrayList(E[] array, ArrayList<E> list) {
	for (int i = 0; i < array.length; i++) {
		list.add(array[i]);
	}
}

در این متد جنریک دو پارامتر دریافت می‌شود:

اولی آرایه‌ای از نوع E به نام array

دومی آرایه لیستی (که در قسمت قبل با آن آشنا شدید) از نوع E به نام list

بنابراین نوع داده آرایه و آرایه لیست باید مثل هم باشد.

سپس همانطور که می‌بینید حلقه‌ای نوشته شده که عناصر آرایه array را به list اضافه می‌کند. بین کلمات public و void هم پارامتر جنریک این متد نوشته شده است.

مثالی برای استفاده از این متد:

Main obj = new Main();
Integer[] arr = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>();
obj.arrayToArrayList(arr, list);

فرض می‌کنیم متد بالا را در کلاسی به نام Main تعریف کرده‌ایم. آرایه‌ای به نام arr از نوع Integer با سه مقدار داریم. (با کلاس Integer در قسمت قبل آشنا شدید) سپس آرایه لیستی به نام list هم از نوع Integer تعریف کردیم. سپس متد arrayToArrayList را از شی obj فراخوانی کردیم و arr و list را به آن دادیم.

شاید این سوال پیش بیاید که با اینکه مقادیری که Integer نگهداری می‌کند در واقع همان مقادیر از نوع int هستند چرا نوع داده آرایه arr را int تعریف نکردیم؟

نکته اینجاست که بر خلاف کلاس‌های جنریک که نوع پارامتر جنریک آن را هنگام ساختن شی از آن صراحتا اعلام می‌کردیم، در متدهای جنریک نوع پارامتر جنریک را صراحتا مشخص نمی‌کنیم بلکه نوع پارامتر جنریک با توجه به نوع داده پارامترهای متد تعیین می‌شود. پس همانطور که هنگام تعریف شی از کلاس‌های جنریک باید حتما نوع پارامتر جنریک را یکی از Reference Type ها تعریف می‌کردیم، پارامترهای این متد هم باید حتما از نوع یکی از Reference Type ها باشد.

چون پارامترهایی که به این متد داده‌ایم از نوع Integer هستند بنابراین پارامتر جنریک متد هم Integer در نظر گرفته می‌شود.

نکته دیگر اینکه در تعریف متدهای جنریک فقط محدود به تعریف یک پارامتر جنریک نیستیم.

همچنین مانند کلاس‌های جنریک، پارامتر جنریک متدهای جنریک را نیز می‌توان محدودسازی کرد. مثلا arrayToArrayList را می‌توان به این صورت نوشت:

public <E extends Number> void arrayToArrayList(E[] array, ArrayList<E> list) {
}

سازنده‌های جنریک (Generic Constructors)

یک سازنده می‌تواند جنریک باشد حتی اگر کلاسی که در آن تعریف شده غیر جنریک باشد.

مثال:

public class Main {
	private int number;
	
	public <T extends Number> Main(T number) {
		this.number = number.intValue();
	}
}

همانطور که می‌بینید کلاس Main فیلدی به نام number از نوع int دارد. کلاس Number که کلاس پدر تمام کلاس‌های wrapper مربوط به اعداد است دارای متدهایی است و بنابراین کلاس‌هایی که از Number ارث‌بری دارند نیز این متدها را دارند. مثلا متد intValue که در این کد از آن استفاده کردیم، مقدار صحیح عددی که در متغیر T ذخیره شده است را بر‌می‌گرداند. حال متد intValue اگر T از نوع اعداد صحیح باشد که همان عدد و اگر از نوع اعداد اعشاری باشد مقدار صحیح آن عدد را برمی‌گرداند.

البته نکته‌ای که باید توجه داشت این است که اگر در یک کلاس غیر جنریک یک سازنده جنریک داشته باشیم آنگاه از پارامتر جنریک آن سازنده فقط در همان سازنده می‌توان استفاده کرد چون آن پارامتر جای دیگری در کلاس تعریف نشده است.

اینترفیس‌های جنریک (Generic Interfaces)

اینترفیس‌ها نیز در جاوا قابلیت جنریک‌شدن دارند.

مثال:

interface GenericInterface<T> {
    void setT(T t);    
 
    T getT();
}

در استفاده از اینترفیس‌های جنریک باید به چند نکته توجه داشت:

۱ – کلاس جنریکی که یک اینترفیس جنریک را پیاده‌سازی می‌کند باید حداقل به تعداد پارامترهای جنریک آن اینترفیس پارامتر جنریک داشته باشد و نوع آن نیز باید با نوع پارامتر جنریک اینترفیس برابر باشد. البته کلاس می‌تواند پارامترهای جنریک مختص به خود را نیز داشته باشد.

مثال:

class GenericClass1<T> implements GenericInterface<T> {
    
}

مثلا این کلاس جنریک تنها یک پارامتر جنریک دارد و آن‌ هم همان پارامتر جنریک اینترفیس GenericInterface است. واضح است که هنگام تعریف شی از این کلاس هر نوع داده‌ای که به عنوان T به کلاس داده شود همان نوع هم به عنوان T به اینترفیس GenericInterface داده خواهد شد.

کلاس زیر علاوه بر پارامتر جنریک T که باید داشته باشد یک پارامتر دیگر به نام V نیز دارد:

class GenericClass2<T, V> implements GenericInterface<T> {

}

اما کلاس زیر صحیح نیست چون اینترفیسی که پیاده‌سازی کرده دو پارامتر جنریک دارد اما کلاس فقط یکی از پارامترهای آن را برای خود تعریف کرده است:

class GenericClass3<T> implements GenericInterface<T, V> {

}

چند نکته راجع به جنریک‌ها

۱ – از پارامترهای جنریک نمی‌توان شی ساخت. مثلا کد زیر اشتباه است و کامپایل نمی‌شود:

public class Gen<T> {
	T ob;

	public Gen() {
		ob = new T();
	}
}

۲ – اعضای استاتیک کلاس نمی‌توانند به پارامترهای جنریک کلاس دسترسی پیدا کنند. مثلا کد زیر اشتباه است:

public class Gen<T> {
	T ob;
	
	public static T getOb() {
		return T;
}	
}

البته می‌توان متدهای جنریک استاتیک تعریف کرد که پارامترهای جنریک مخصوص خود را داشته باشند.

1 نظر
  1. Morteza می گوید

    سلام و درود. وبسایت و محتوا که عالیه . فقط یه سوال. من فقط با پایتون آشنا هستم و میخوام برم سراغ اندروید به نظرتون با html وcssوjavascripet شروع کنم بهتر نیست؟ چون یه دید کلی تر میده مثلا html شبیه xml و…؟ و مدت کوتاه ترین میشه یاد گرفت و بعد برم سراغ جاوا و بعدش اندروید یه راهنمایی کنین ممنونم

ارسال یک پاسخ

آدرس ایمیل شما منتشر نخواهد شد.