معرفی سریع
به طور کلی تا قبل از نسخه 8 جاوا، هربار قصد داشتیم تا عملکردی را پیادهسازی کنیم، مجبور بودیم آن را داخل یک کلاس قرار دهیم. به عبارت دیگر هر تابعی که مینویسیم، بخشی از یک کلاس و درواقع بخشی از یک شیء خواهد بود.
این مسئله از آنجا که زبان جاوا (و زبان اندروید) شیء گراست، اصلا نمیتواند اتفاق عجیبی باشد. اما گاهی این مسئله برای ما محدودیت ایجاد میکند. مثلا اگر بخواهیم تابعی برای جمع دو عدد بنویسیم، چه نیازی است که حتما آن را در قالب یک کلاس بنویسیم؟ آیا بهتر نبود که بتوانیم صرفا “عملکرد” هایمان را بنویسیم و نیازی به تعریفِ کلاسها برای آنها نداشتیم؟
بهتر نمیشد اگر میتوانستیم یک قدم جلوتر رفته و حتی با علمکردها مثل متغیرها رفتار کنیم؟
یعنی همانطور که اعداد صحیح، اعداد اعشاری و رشتهها و امثال آن را تعریف و از آنها استفاده میکنیم، بتوانیم عملکردها را هم به شکل متغیر تعریف کنیم و از آن در بخشهای مختلف برنامه استفاده کنیم.
این یکی از مزیتها و اهداف عبارات لامبداست.
علاوه بر این، عبارات لامبدا به ما اجازه پردازش موازی کارها را نیز میدهند.
عبارات لامبدا از Functional interfaceها برای تعریف خود استفاده میکنند (اگر نمیدانید، بدانید که اینترفیسهایی که صرفا یک تابع abstract داخل خود دارند را functional interface مینامند؛ مثلا اگر به اینترفیس Runnable که در اندروید کاربرد زیادی هم دارد نگاهی بیاندازیم، میبینیم که فقط یک تابع run داخل خود دارد و به تبع، functional interface است).
عملگر فلش
عبارات لامبدا یک عملگر جدید که عملگر فلش یا Arrow نام دارد را به جاوا اضافه کرده است. این عملگر عبارات لامبدا را به دو بخش تقسیم میکند:
(n) -> n*n
سمت چپ پارامترهایی را که برای عبارت مورد نیاز است را مشخص میکند، که اگر پارامتری مورد نیاز نیست، میتواند خالی باشد.
سمت راست بدنه عبارت لامبدا است که عملیات عبارت لامبدا را مشخص میکند.
بد نیست اگر به این عملگر به عنوان واژهی “میشود” نگاه کنیم. مثلا “n میشود n*n”.
با داشتن دانش در مورد عملگر فلش و functional interfaceها، میشود یک عبارت ساده لامبدا را پیادهسازی کرد:
interface NumericTest { boolean computeTest(int n); } public static void main(String args[]) { NumericTest isEven = (n) -> (n % 2) == 0; NumericTest isNegative = (n) -> (n < 0); // Output: false System.out.println(isEven.computeTest(5)); // Output: true System.out.println(isNegative.computeTest(-5)); }
وقتی یک عبارت لامبدا مینویسید، میتوانید نوع پارامتر را نیز در عبارت مثل این تعریف کنید:
MyGreeting morningGreeting = (String str) -> "Good Morning " + str + "!"; MyGreeting eveningGreeting = (String str) -> "Good Evening " + str + "!";
قراردادن عبارات لامبدا در بلاک
تا الان، عبارات لامبدای تکخطی را دیدیم، یک نوع دیگر هم از عبارات لامبدا، وقتی است که سمتِ راستِ فلش چند خط داشته باشیم، در این حالت لامبدا را در بلاک نوشته و در انتهای بلاک سیمیکالن قرار میدهیم. مثلا:
interface MyString { String myStringFunction(String str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverseStr = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr.myStringFunction("Lambda Demo")); }
توابع Functional عمومی
یک عبارت لامبدا نمیتواند به صورت generic نوشته شود. اما functional interface نسبت داده شده به عبارت لامبدا میتواند. میشود یک اینترفیس generic نوشت و از آن برای پشتیبانی از انواع خروجی و ورودیهای مختلف استفاده کرد:
interface MyGeneric<T> { T compute(T t); } public static void main(String args[]){ // String version of MyGenericInteface MyGeneric<String> reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Integer version of MyGeneric MyGeneric<Integer> factorial = (Integer n) -> { int result = 1; for(int i=1; i <= n; i++) result = i * result; return result; }; // Output: omeD adbmaL System.out.println(reverse.compute("Lambda Demo")); // Output: 120 System.out.println(factorial.compute(5));
عبارات لامبدا به عنوان ورودی توابع
یکی از کاربردهای متداول عبارات لامبدا، این است که از آنها به عنوان ورودی توابع استفاده کنیم.
این قابلیت خیلی کاربردی است، چون اجازه اینکه کدهای اجرایی را به عنوان آرگومان به توابع پاس کنیم را به ما میدهد.
برای ارسال یک عبارت لامبدا به عنوان ورودی تابع، فقط باید مطمئن باشید که نوع functional interface با نوع مورد انتظار همخوانی دارد.
interface MyString { String myStringFunction(String str); } public static String reverseStr(MyString reverse, String str){ return reverse.myStringFunction(str); } public static void main (String args[]) { // Block lambda to reverse string MyString reverse = (str) -> { String result = ""; for(int i = str.length()-1; i >= 0; i--) result += str.charAt(i); return result; }; // Output: omeD adbmaL System.out.println(reverseStr(reverse, "Lambda Demo"));
واقعا خجالت اوره که حتی بلد نیستی توابع رو استاندارد نام گذاری کنی
سلام امیرحسین جان،
حتی اگر بلد نباشم هم از نظرِ من این خجالتآور نیست
شاید بهتر باشه موردی بگی چه جاهایی رو اشتباه انجام دادم، تا خودم رو اصلاح کنم و بیشتر یاد بگیرم.
ممنونم که نظرت رو گفتی.
سلام
ممنون از آموزش هاتون
لطفاً لینک فایل ها رو هم بزارید،دانلودش سخته
سلام قربان، خواهش میکنم.
منظورتون کدوم فایلهاست؟
خودِ ویدئوها یا فایل پروژه؟
تو زمینه ای که فعالیت میکنید جزو بهترین
سایت ها هستید.
وای خیلی خوبه ساییتون