CodeGym /وبلاگ جاوا /Random-FA /نمونه های خاص از کلاس های انتزاعی در جاوا
John Squirrels
مرحله
San Francisco

نمونه های خاص از کلاس های انتزاعی در جاوا

در گروه منتشر شد
سلام! در درس‌های گذشته، با رابط‌ها آشنا شدیم و متوجه شدیم که برای چه هستند. موضوع امروز تکرار موضوع قبلی خواهد بود. بیایید در مورد کلاس های انتزاعی در جاوا صحبت کنیم. نمونه های خاص از کلاس های انتزاعی در جاوا - 1

چرا کلاس ها "انتزاعی" نامیده می شوند

احتمالاً به یاد دارید که "انتزاع" چیست - ما قبلاً آن را مرور کرده ایم. :) اگر فراموش کردید، نترسید. به یاد داشته باشید: این یک اصل از OOP است که می گوید هنگام طراحی کلاس ها و ایجاد اشیا، باید فقط ویژگی های اصلی موجودیت را شناسایی کنیم و جزئی را کنار بگذاریم. به عنوان مثال، اگر ما در حال طراحی یک کلاس هستیم ، به سختی به ویژگی " heightSchoolTeacher " نیاز داریم . در واقع، این ویژگی برای یک معلم بی ربط است. اما اگر ما در حال ایجاد یک کلاس هستیم، آنگاه رشد یک ویژگی مهم خواهد بود. پس گوش کن یک کلاس انتزاعی به همان اندازه انتزاعی است که وجود دارد - یک «خالی» ناتمام برای گروهی از کلاس‌های آینده. جای خالی را نمی توان همانطور که هست استفاده کرد. خیلی «خام» است. اما وضعیت خاصی و رفتار کلی را توصیف می کند که توسط کلاس های آینده که کلاس انتزاعی را به ارث می برند، خواهند داشت. BasketballPlayer

نمونه هایی از کلاس های انتزاعی جاوا

یک مثال ساده را در مورد خودروها در نظر بگیرید:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
این همان چیزی است که ساده ترین کلاس انتزاعی به نظر می رسد. همانطور که می بینید، چیز خاصی نیست :) چرا به آن نیاز داریم؟ اول از همه، موجودیت مورد نیاز ما، یک خودرو را به انتزاعی ترین شکل ممکن توصیف می کند. دلیلی وجود دارد که ما از کلمه انتزاعی استفاده می کنیم . در دنیای واقعی، هیچ «ماشین انتزاعی» وجود ندارد. کامیون ها، ماشین های مسابقه ای، سدان ها، کوپه ها و SUV ها وجود دارد. کلاس انتزاعی ما صرفاً یک "طرح" است که بعداً برای ایجاد کلاس های خودرو از آن استفاده خواهیم کرد.
public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}
این بسیار شبیه به چیزی است که در درس های ارث در مورد آن صحبت کردیم. اما در آن درس ها ما کلاس ماشین داشتیم و روش های آن انتزاعی نبود. اما این راه حل دارای تعدادی اشکال است که در کلاس های انتزاعی رفع می شوند. اول از همه، شما نمی توانید یک نمونه از یک کلاس انتزاعی ایجاد کنید :
public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
سازندگان جاوا به طور خاص این "ویژگی" را طراحی کردند. یک بار دیگر، به عنوان یادآوری: یک کلاس انتزاعی فقط یک طرح اولیه برای کلاس های "عادی" آینده است . شما نیازی به کپی از نقشه ندارید، درست است؟ و شما نمونه هایی از یک کلاس انتزاعی ایجاد نمی کنید :) اما اگر کلاس Carانتزاعی نبود، می توانیم به راحتی نمونه هایی از آن ایجاد کنیم:
public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // Some logic
   }

    public void brake() {
       // Some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is fine. A car is created.
   }
}
اکنون برنامه ما نوعی ماشین غیرقابل درک دارد - نه یک کامیون، نه یک ماشین مسابقه ای، نه یک سدان، و کاملاً نامشخص است که چیست. این همان «ماشین انتزاعی» است که در طبیعت وجود ندارد. ما می توانیم همین مثال را با استفاده از حیوانات ارائه دهیم. اگر Animalکلاس ها ( حیوانات انتزاعی ) را تصور کنید. معلوم نیست چه نوع حیوانی است، به چه خانواده ای تعلق دارد و چه ویژگی هایی دارد. دیدن آن در برنامه شما عجیب است. هیچ "حیوان انتزاعی" در طبیعت وجود ندارد. فقط سگ، گربه، روباه، خال و غیره. کلاس های انتزاعی ما را از اشیاء انتزاعی نجات می دهند. آنها به ما حالت و رفتار اساسی می دهند. مثلا همه ماشین ها باید مدل و رنگ و حداکثر سرعت داشته باشند و بتوانید گاز و ترمز بزنید . خودشه. این یک طرح انتزاعی کلی است. سپس کلاس های مورد نیاز خود را طراحی می کنید. نکته: دو متد در کلاس abstract نیز به عنوان abstract تعیین می شوند و هیچ پیاده سازی ندارند. دلیل یکسان است: کلاس های انتزاعی رفتار پیش فرض را برای اتومبیل های انتزاعی ایجاد نمی کنند. آنها فقط نشان می دهند که هر ماشینی باید بتواند انجام دهد. با این حال، اگر به رفتار پیش‌فرض نیاز دارید، می‌توانید متدها را در یک کلاس انتزاعی پیاده‌سازی کنید. جاوا این را ممنوع نمی کند:
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Gas!");
   }

   public abstract void brake();

   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
خروجی کنسول : “ Sedanگاز !gas() تا کلاس والد انتزاعی افزایش می یابد Car، اما ما brake()متد را در Sedanکلاس لغو کردیم. این بسیار راحت و انعطاف پذیر است. اما اکنون کلاس ما آنقدر انتزاعی نیست ؟ بالاخره نیمی از متدهای آن پیاده سازی شده است. در واقع یک ویژگی بسیار مهم است - یک کلاس انتزاعی است اگر حداقل یکی از متدهای آن انتزاعی باشد . یکی از دو متد یا حداقل یکی از هزاران متد - تفاوتی ندارد. حتی می‌توانیم همه متدها را پیاده‌سازی کنیم و هیچ کدام را رها نکنیم. سپس یک کلاس انتزاعی بدون متدهای انتزاعی خواهد بود. در اصل، این امکان پذیر است و کامپایلر خطایی ایجاد نمی کند، اما بهتر است از آن اجتناب کنید: کلمه abstract معنای خود را از دست می دهد و برنامه نویسان همکار شما این کار را انجام خواهند داد . خیلی شگفت زده باشید:/ در عین حال، اگر متدی با کلمه abstract مشخص شده باشد، هر کلاس فرزند باید آن را پیاده سازی کند یا آن را به عنوان abstract اعلام کند. در غیر این صورت، کامپایلر یک خطا ایجاد می کند. البته، هر کلاس می تواند تنها یک کلاس انتزاعی را به ارث ببرد، بنابراین از نظر وراثت تفاوتی بین کلاس های انتزاعی و معمولی وجود ندارد. فرقی نمی کند که یک کلاس انتزاعی را به ارث ببریم یا یک کلاس معمولی، فقط یک کلاس والد می تواند وجود داشته باشد.

چرا جاوا چندین وراثت کلاس ندارد؟

قبلاً گفته‌ایم که جاوا وراثت چندگانه ندارد، اما واقعاً دلیل آن را بررسی نکرده‌ایم. بیایید سعی کنیم این کار را انجام دهیم. واقعیت این است که اگر جاوا چندین وراثت داشته باشد، کلاس های فرزند نمی توانند تصمیم بگیرند که کدام رفتار خاص را انتخاب کنند. فرض کنید ما دو کلاس داریم - Toasterو NuclearBomb:
public class Toaster {


 public void on() {

       System.out.println("The toaster is on. Toast is being prepared!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
همانطور که می بینید، هر دو یک on()روش دارند. برای یک توستر، شروع به برشته کردن می کند. برای بمب اتمی، باعث انفجار می شود. اوه: / حالا تصور کنید که تصمیم گرفتید (از من نپرسید چرا!) چیزی در این بین ایجاد کنید. و به این ترتیب شما یک MysteriousDeviceکلاس دارید! این کد، البته، کار نمی کند، و ما فقط آن را به عنوان مثال ارائه می دهیم "اما می تواند باشد":
public class MysteriousDevice extends Toaster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // So what should happen here? Do we get toast or a nuclear apocalypse?
   }
}
بیایید نگاهی به آنچه داریم بیندازیم. این دستگاه مرموز به طور همزمان توستر و بمب هسته ای را به ارث می برد. on()هر دو روش دارند . در نتیجه، اگر متد را فراخوانی کنیم on()، مشخص نیست که کدام یک باید روی MysteriousDeviceشیء فراخوانی شود. هیچ راهی وجود ندارد که شی هرگز بتواند آن را بشناسد. و برای تکمیل همه چیز: بمب هسته ای روشی ندارد off()، بنابراین اگر درست حدس زده باشیم، غیرفعال کردن دستگاه غیرممکن خواهد بود. نمونه های خاص از کلاس های انتزاعی در جاوا - 2دقیقاً به دلیل این «آشفتگی»، جایی که شی نمی‌داند چه رفتاری را نشان دهد، سازندگان جاوا ارث چندگانه را رها کردند. با این حال، به یاد دارید که کلاس های جاوا می توانند چندین رابط را پیاده سازی کنند. ضمناً، در مطالعات خود، قبلاً با حداقل یک کلاس انتزاعی مواجه شده اید! هرچند شاید هم متوجه نشدی :)
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
این دوست قدیمی شما، Calendarکلاس است. انتزاعی است و چندین فرزند دارد. یکی از آنها است GregorianCalendar. قبلاً از آن در درس های مربوط به تاریخ استفاده کرده اید. :) همه چیز به اندازه کافی واضح به نظر می رسد. فقط یک سوال وجود دارد: به هر حال تفاوت اساسی بین کلاس های انتزاعی و رابط ها چیست؟ چرا آنها به جای محدود کردن زبان به یک زبان، هر دو را به جاوا اضافه کردند؟ به هر حال، این کاملاً کافی بود. در درس بعدی در مورد این صحبت خواهیم کرد ! تا آن موقع :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION