JavaRush /وبلاگ جاوا /Random-FA /کلاس ها، انواع کلاس های تو در تو همراه با مثال
Ярослав
مرحله
Днепр

کلاس ها، انواع کلاس های تو در تو همراه با مثال

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

کلاس چیست؟

یک کلاس یک توصیف منطقی از چیزی است، یک الگو که با آن می توانید نمونه های واقعی آن چیز را ایجاد کنید. به عبارت دیگر، این به سادگی توصیفی است از اینکه موجودیت های ایجاد شده چگونه باید باشند: چه ویژگی ها و روش هایی باید داشته باشند. ویژگی ها ویژگی های یک موجودیت هستند، روش ها اقداماتی هستند که می تواند انجام دهد. یک مثال خوب از یک کلاس از زندگی واقعی، که درک درستی از چیستی یک کلاس را به دست می دهد، می توان نقشه ها را در نظر گرفت: نقشه ها برای توصیف سازه ها (منجنیق، پیچ گوشتی) استفاده می شوند، اما طراحی یک طرح نیست. همانطور که مهندسان از نقشه ها برای ایجاد طرح ها استفاده می کنند، برنامه نویسی نیز از کلاس ها برای ایجاد اشیایی استفاده می کند که ویژگی ها و روش ها را توصیف می کنند.
public class Student {
    private String name, group, specialty;

    public Student(String name, String group, String specialty) {
       this.name = name;
       this.group = group;
       this.specialty = specialty;
   }

   // getters/setters
}
در این مثال، ما یک کلاس جاوا ایجاد کردیم که موجودیت "دانشجو" را توصیف می کند: هر دانش آموز یک نام، گروه و تخصص دارد. حال در جاهای دیگر برنامه می توانیم نمونه های واقعی این کلاس را ایجاد کنیم. به عبارت دیگر: اگر کلاس Studentتصویری از آن چیزی است که یک دانش آموز باید باشد، پس نمونه ایجاد شده خود دانش آموز واقعی است. نمونه ای از ایجاد دانش آموز جدید: new Student("Ivan", "KI-17-2", "Computer Engineering");عملگر newکلاس را جستجو می کند Studentو سپس متد خاصی (سازنده) این کلاس را فراخوانی می کند. سازنده یک شی کلاس آماده را برمی گرداند Student- دانشجوی عزیز گرسنه ما بدون بورس :))

انواع کلاس ها در جاوا

در جاوا 4 نوع کلاس در یک کلاس دیگر وجود دارد:
  1. کلاس های داخلی تو در تو کلاس های غیر ایستا در داخل یک کلاس بیرونی هستند.

  2. کلاس‌های استاتیک تودرتو ، کلاس‌های ثابت داخل یک کلاس بیرونی هستند.

  3. کلاس های محلی جاوا کلاس های درون متد هستند.

  4. کلاس های جاوای ناشناس کلاس هایی هستند که در جریان ایجاد می شوند.

در مورد هر یک به طور جداگانه صحبت خواهیم کرد.

کلاس های غیر استاتیک در داخل یک کلاس بیرونی

ابتدا، می خواهم با یک مثال واقعی بفهمید که این چیست، زیرا درک آن را بسیار آسان تر می کند. بنابراین اکنون یک چیز بزرگ واقعی را به اجزای کوچکتر تقسیم می کنیم و یک هواپیما را جدا می کنیم! با این حال، برای مثال کافی است کمی نشان دهیم؛ ما آن را به طور کامل تجزیه نمی کنیم. برای تجسم این فرآیند، از نمودار هواپیما استفاده می کنیم. کلاس ها، انواع کلاس های تو در تو با مثال - 2 ابتدا باید کلاسی ایجاد کنیم Airplaneکه در آن بتوانیم توضیحات کمی اضافه کنیم: نام هواپیما، کد شناسایی، پرواز.
public class Airplane {
    private String name, id, flight;

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    // getters/setters
}
حالا می خواهیم بال ها را اضافه کنیم. یک کلاس جداگانه ایجاد کنید؟ شاید این منطق باشد اگر برنامه پیچیده ای برای طراحی هواپیما داشته باشیم و باید تعداد زیادی کلاس مشتق شده ایجاد کنیم (کلاس هایی که منطق کلاس مادر را دارند، یعنی کلاسی که از آن به ارث می برند، اما بنابراین آنها کلاس والد را با اضافه کردن منطق یا ویژگی های دقیق تر گسترش می دهند، اما اگر فقط یک بازی داشته باشیم که در آن یک هواپیما داشته باشیم چه؟ سپس برای ما منطقی تر خواهد بود که کل ساختار را در یک مکان (در یک کلاس) تکمیل کنیم. اینجاست که کلاس های تو در تو غیر استاتیک وارد بازی می شوند. اساساً، این شرح مفصل تری از برخی جزئیات کلاس خارجی ما است. در این مثال، ما باید بال هایی برای یک هواپیما ایجاد کنیم - چپ و راست. بیایید ایجاد کنیم!
public class Airplane {
    private String name, id, flight;
    private Wing leftWing = new Wing("Red", "X3"), rightWing = new Wing("Blue", "X3");

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    private class Wing {
        private String color, model;

        private Wing(String color, String model) {
            this.color = color;
            this.model = model;
        }

        // getters/setters
    }

    // getters/setters
}
Wingبنابراین ما یک کلاس تو در تو (بال) غیر ایستا در داخل یک کلاس Airplane(هواپیما) ایجاد کردیم و دو متغیر - بال چپ و بال راست را اضافه کردیم. و هر بال دارای خواص (رنگ، ​​مدل) خاص خود است که می توانیم آنها را تغییر دهیم. به این ترتیب می توانید به اندازه نیاز سازه ها را پرسنل کنید. و توجه داشته باشید: قبلاً در نمودار قطعات بسیار زیادی برای هواپیما وجود داشت و در واقع می‌توانیم تمام قطعات را به کلاس‌های داخلی تقسیم کنیم، اما چنین فرآیندی همیشه توصیه نمی‌شود. چنین لحظاتی بسته به کار باید ردیابی شوند. ممکن است برای حل مشکل اصلاً نیازی به بال نداشته باشید. سپس نیازی به انجام آنها نیست. این مانند بریدن یک فرد به پاها، بازوها، تنه و سر است - ممکن است، اما چرا اگر این کلاس فقط برای ذخیره داده‌های مربوط به افراد استفاده می‌شود؟ ویژگی های کلاس های جاوا تو در تو غیر ایستا:
  1. آنها فقط در اشیا وجود دارند، بنابراین برای ایجاد آنها به یک شی نیاز دارید. به عبارت دیگر: ما بال خود را طوری طراحی کردیم که بخشی از هواپیما باشد، بنابراین برای ایجاد بال به هواپیما نیاز داریم، در غیر این صورت به آن نیازی نداریم.
  2. در کلاس جاوا نمی توان متغیرهای ثابتی وجود داشته باشد. اگر به مقداری ثابت یا هر چیز ثابت دیگری نیاز دارید، باید آنها را به یک کلاس بیرونی منتقل کنید. این به دلیل اتصال نزدیک کلاس تو در تو غیر ایستا به کلاس خارجی است.
  3. کلاس دسترسی کامل به تمام فیلدهای خصوصی کلاس خارجی دارد. این ویژگی به دو صورت کار می کند.
  4. شما می توانید به یک نمونه از یک کلاس خارجی اشاره کنید. مثال: Airplane.this یک پیوند به یک هواپیما است، این یک پیوند به یک بال است.

کلاس های استاتیک در داخل یک کلاس بیرونی

این نوع کلاس هیچ تفاوتی با یک کلاس خارجی معمولی ندارد، به جز یک چیز: برای ایجاد نمونه ای از چنین کلاسی، باید کل مسیر از کلاس خارجی تا کلاس مورد نظر را لیست کنید که با یک نقطه از هم جدا شده اند. به عنوان مثال: Building.Plaftorm platform = new Building.Platform(); از کلاس های استاتیک برای قرار دادن کلاس های مرتبط در کنار هم استفاده می شود تا کار با ساختار منطقی آسان تر باشد. به عنوان مثال: ما می توانیم یک کلاس خارجی ایجاد کنیم Building، جایی که لیست خاصی از کلاس ها وجود دارد که یک ساختمان خاص را نشان می دهد.
public abstract class Building {
    private String name, address, type;

    Building(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public static class Platform extends Building {
        public Platform(String name, String address) {
            super(name, address);
            setType("Platform");
        }

        // some additional logic
    }

    public static class House extends Building {
        public House(String name, String address) {
            super(name, address);
            setType("House");
        }

        // some additional logic
    }

    public static class Shop extends Building {
        public Shop(String name, String address) {
            super(name, address);
            setType("Shop");
        }

        // some additional logic
    }

    // getters/setters
}
این مثال نشان می‌دهد که چگونه کلاس‌های استاتیک به شما اجازه می‌دهند یک ساختار منطقی را به شکل راحت‌تری بسته‌بندی کنید. اگر آنها وجود نداشتند، باید 4 کلاس کاملاً متفاوت ایجاد کنیم. مزایای این روش:
  1. تعداد کلاس ها کاهش یافته است.
  2. همه کلاس ها داخل کلاس والد خود هستند. ما قادریم کل سلسله مراتب را بدون باز کردن هر کلاس به طور جداگانه ردیابی کنیم.
  3. می‌توانیم به کلاس Building مراجعه کنیم، و IDE قبلاً کل لیست تمام زیر کلاس‌های این کلاس را نشان می‌دهد. این کار پیدا کردن کلاس‌های مورد نیاز را آسان‌تر می‌کند و کل تصویر را به‌طور کلی‌تر نشان می‌دهد.
نمونه ای از ایجاد نمونه ای از کلاس استاتیک تودرتو:Building.Shop myShop = new Building.Shop(“Food & Fun!”, “Kalyaeva 8/53”); همچنین می خواهم توجه داشته باشم که این استراتژی در کلاس های AWT 2D برای توصیف اشکال مانند Line2D، Arc2D، Ellipse2D و موارد دیگر استفاده می شود.

کلاس های محلی

این کلاس ها در روش های دیگر اعلام می شوند. در واقع، آنها تمام خصوصیات یک کلاس تودرتوی غیراستاتیک را دارند، فقط نمونه های آنها را می توان فقط در یک متد ایجاد کرد، و متد نمی تواند ثابت باشد (برای ایجاد آنها به یک نمونه از یک کلاس خارجی نیاز دارید، یک مرجع به یک نمونه ای از شی فراخوان به طور ضمنی به روش های غیر استاتیک منتقل می شود و در روش ایستا هیچ روشی برای این پیوند وجود ندارد). اما آنها ویژگی های خاص خود را دارند:
  1. کلاس های محلی فقط می توانند با متغیرهای متد نهایی کار کنند. موضوع این است که نمونه‌های کلاس‌های محلی را می‌توان پس از تکمیل متد در پشته ذخیره کرد و متغیر را پاک کرد. اگر متغیر نهایی اعلام شود، کامپایلر می تواند یک کپی از متغیر را برای استفاده بعدی توسط شی ذخیره کند. و یک چیز دیگر: از نسخه های 8+ جاوا، می توانید از متغیرهای غیر نهایی در کلاس های محلی استفاده کنید، اما به شرطی که تغییر نکنند.
  2. کلاس های محلی را نمی توان با اصلاح کننده های دسترسی اعلام کرد.
  3. کلاس های محلی به متغیرهای متد دسترسی دارند.
کلاس های محلی به ندرت یافت می شوند، زیرا آنها خواندن کد را دشوار می کنند و هیچ مزیتی ندارند، به جز یکی - دسترسی به متغیرهای متد. من نمی دانم چه مثالی از یک کلاس محلی می توان گرفت که استفاده مؤثر از آنها را نشان دهد، بنابراین من فقط مثال خود را نشان می دهم. بیایید بگوییم که ما یک طبقه داریم Person(فرض می شود که این یک شخص است) دارای خواص street(خیابان)، house(خانه). ما می‌خواهیم برخی از شی‌ها را برای دسترسی به مکان آن شخص برگردانیم. برای انجام این کار، رابط AddressContainer را ایجاد کردیم که به معنای ذخیره سازی داده ها در مورد مکان یک شخص است.
public class Person {
    private String name, street, house;

    public Person(String name, String street, String house) {
        this.name = name;
        this.street = street;
        this.house = house;
    }

    private interface AddressContainer {
        String getStreet();
        String getHouse();
    }

    public AddressContainer getAddressContainer() {
        class PersonAddressContainer implements AddressContainer {
            final String street = Person.this.street, house = Person.this.house;

            @Override
            public String getStreet() {
                return this.street;
            }

            @Override
            public String getHouse() {
                return this.house;
            }
        }

        return new PersonAddressContainer();
    }

    public static void main(String[] args) {
        Person person = new Person("Nikita", "Sholohova", "17");

        AddressContainer address = person.getAddressContainer();

        System.out.println("Address: street - " + address.getStreet() + ", house - " + address.getHouse());
    }

    // getters/setters
}
همانطور که می بینید، در داخل متد یک کلاس ایجاد کردیم که ذخیره مکان یک شخص را پیاده سازی می کند، متغیرهای ثابتی را در آنجا ایجاد کردیم (به طوری که پس از خروج از متد، متغیرها در یک شی ذخیره شدند) و یک متد برای به دست آوردن آدرس و پیاده سازی کردیم. خانه حال می توانیم از این شی در جاهای دیگر برنامه برای بدست آوردن موقعیت مکانی یک شخص استفاده کنیم. من می‌دانم که این مثال ایده‌آل نیست و درست‌تر است که این کار را صرفاً با گذاشتن دریافت‌کننده‌ها در کلاس انجام دهیم Person، با این حال، ایجاد این کلاس و استفاده احتمالی آن نشان داده شد، و سپس این به شما بستگی دارد.

کلاس های ناشناس

در زیر هود، کلاس های ناشناس فقط کلاس های تودرتو غیراستاتیک معمولی هستند. ویژگی آنها سهولت استفاده آنهاست. هنگام ایجاد نمونه ای از کلاس دیگر می توانید کلاس خود را مستقیماً بنویسید.
public class Animal {
    public void meow() {
        System.out.println("Meow!");
    }

    public static void main(String[] args) {
        Animal anonTiger = new Animal() {
            @Override
            public void meow() {
                System.out.println("Raaar!");
            }
        };

        Animal notAnonTiger = new Animal().new Tiger();

        anonTiger.meow(); // будет выведено Raaar!
        notAnonTiger.meow(); // будет выведено Raaar!
    }

    private class Tiger extends Animal {
        @Override
        public void meow() {
            System.out.println("Raaar!");
        }
    }
}
اساسا، ما به سادگی دو چیز را در یک مکان ترکیب می کنیم: ایجاد یک نمونه از یک کلاس ( Animal) و ایجاد یک نمونه از کلاس داخلی وارث آن ( Tiger). در غیر این صورت، باید کلاس را جداگانه ایجاد کنیم و برای رسیدن به همان نتیجه از ساختارهای طولانی تر استفاده کنیم. استفاده از کلاس های ناشناس در بسیاری از موارد توجیه می شود، به ویژه زمانی که:
  • بدنه کلاس بسیار کوتاه است.
  • فقط یک نمونه از کلاس مورد نیاز است.
  • کلاس در مکانی که در آن ایجاد شده است یا بلافاصله پس از آن استفاده می شود.
  • نام کلاس مهم نیست و درک کد را آسان تر نمی کند.
کلاس های ناشناس اغلب در رابط کاربری گرافیکی برای ایجاد کنترل کننده رویداد استفاده می شوند. به عنوان مثال، برای ایجاد یک دکمه و واکنش به کلیک آن:
JButton b2 = new JButton("Click");
b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата!");
    }
});
با این حال، پس از جاوا 8 شروع به استفاده از عبارات لامبدا کردند، اما هنوز کدهای زیادی قبل از نسخه 8 نوشته شده بود و ممکن است با چنین کتیبه هایی مواجه شوید (و در طول آموزش خود در JavaRush با آنها مواجه خواهید شد).\ آنالوگ با لامبدا:
JButton b2 = new JButton("Click");
b2.addActionListener(e -> System.out.println("Кнопка нажата!"));
پایان مقاله از همه شما برای توجه شما متشکرم و امیدوارم چیز جدیدی یاد گرفته باشید یا چیزی را که قبلاً متوجه نشده بودید. من همچنین می خواهم توضیح دهم که این مقاله متعلق به دسته "توجه به جزئیات" است . این اولین کار من است، بنابراین امیدوارم برای کسی مفید بوده باشد. در آینده نزدیک که ایده های جدید بیاد سعی میکنم یه چیز دیگه بنویسم فقط یه ایده دارم...موفق باشید برای همه و موفقیت در برنامه نویسی :)
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION