JavaRush /Java blogi /Random-UZ /Sinflar, misollar bilan ichki o'rnatilgan sinflarning tur...
Ярослав
Daraja
Днепр

Sinflar, misollar bilan ichki o'rnatilgan sinflarning turlari

Guruhda nashr etilgan
Hammaga salom. Ushbu mavzuda men yangi boshlanuvchilarga ushbu mavzuni tushunishga yordam berish uchun Java darslari va ularning turlari haqida batafsil gaplashmoqchiman va ehtimol yangi boshlamaganlar yangi narsalarni o'rganishadi. Iloji bo'lsa, hamma narsa haqiqiy hayot misollari bilan birga kod misollari yordamida ko'rsatiladi. Qani boshladik. Sinflar, ichki o'rnatilgan sinflarning turlari misollar bilan - 1Shuni ta'kidlashni istardimki, asosiy narsa birinchi ikki turdagi sinflarni tushunishdir va mahalliy va anonim - bu oddiygina ichki sinfning pastki turlari.

Sinf nima?

Sinf - bu biror narsaning mantiqiy tavsifi, shablon, uning yordamida siz o'sha narsaning haqiqiy nusxalarini yaratishingiz mumkin. Boshqacha qilib aytganda, bu yaratilgan ob'ektlar qanday bo'lishi kerakligining oddiy tavsifi: ular qanday xususiyatlarga va usullarga ega bo'lishi kerak. Xususiyatlar ob'ektning xususiyatlari, usullar - u amalga oshirishi mumkin bo'lgan harakatlar. Haqiqiy hayotdan sinfning yaxshi namunasi bo'lib, u sinf nima ekanligini tushunishga imkon beradi, chizmalarni ko'rib chiqish mumkin: chizmalar tuzilmalarni tasvirlash uchun ishlatiladi (katapult, tornavida), lekin chizma dizayn emas. Muhandislar dizaynlarni yaratish uchun chizmalardan foydalanganidek, dasturlash ham xususiyatlar va usullarni tavsiflangan ob'ektlarni yaratish uchun sinflardan foydalanadi.
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
}
Ushbu misolda biz "talaba" ob'ektini tavsiflovchi Java sinfini yaratdik: har bir talabaning ismi, guruhi va mutaxassisligi bor. Endi dasturning boshqa joylarida biz ushbu sinfning haqiqiy namunalarini yaratishimiz mumkin. Boshqacha qilib aytganda: agar sinf Studento'quvchi bo'lishi kerak bo'lgan portret bo'lsa, unda yaratilgan misol haqiqiy talabaning o'zi. Yangi talabani yaratishga misol: new Student("Ivan", "KI-17-2", "Computer Engineering");Operator newsinfni qidiradi Studentva keyin ushbu sinfning maxsus usulini (konstruktorini) chaqiradi. Konstruktor tayyor sinf ob'ektini qaytaradi Student- bizning aziz, och o'quvchimiz stipendiyasiz :))

Java tilidagi sinflar turlari

Java'da boshqa sinf ichida 4 turdagi sinflar mavjud:
  1. Ichki ichki sinflar tashqi sinf ichidagi statik bo'lmagan sinflardir.

  2. Ichki statik sinflar tashqi sinf ichidagi statik sinflardir.

  3. Java mahalliy sinflari usullar ichidagi sinflardir.

  4. Anonim Java sinflari tezda yaratilgan sinflardir.

Biz ularning har biri haqida alohida gaplashamiz.

Tashqi sinf ichidagi statik bo'lmagan sinflar

Birinchidan, haqiqiy misol bilan nima ekanligini tushunishingizni istayman, chunki bu tushunishni ancha osonlashtiradi. Endi biz haqiqiy katta narsani kichikroq qismlarga ajratamiz va samolyotni qismlarga ajratamiz! Biroq, misol uchun ozgina ko'rsatish kifoya qiladi, biz uni to'liq buzmaymiz. Ushbu jarayonni tasavvur qilish uchun biz samolyot diagrammasidan foydalanamiz. Birinchidan, biz bir oz tavsif qo'shadigan Sinflar, misollar bilan ichki o'rnatilgan sinflarning turlari - 2 sinf yaratishimiz kerak : samolyot nomi, identifikatsiya kodi, parvoz.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
}
Endi biz qanotlarni qo'shmoqchimiz. Alohida sinf yaratilsinmi? Agar bizda samolyotlarni loyihalash uchun murakkab dastur bo'lsa va biz juda ko'p sonli hosila sinflarni yaratishimiz kerak bo'lsa, ehtimol bu mantiqdir (ota sinf bilan bir xil mantiqqa ega sinflar, ya'ni ular meros qilib olgan sinflar, lekin shuning uchun ular mantiqiy yoki batafsilroq xususiyatlarni qo'shish orqali ota-ona sinfini kengaytiradilar), lekin bizda bitta samolyot bo'lgan o'yin bo'lsa nima bo'ladi? Keyin butun tuzilmani bir joyda (bir sinfda) yakunlash biz uchun yanada oqilona bo'ladi. Bu erda statik bo'lmagan ichki sinflar o'ynaydi. Aslida, bu bizning tashqi sinfimizning ba'zi tafsilotlarining batafsil tavsifi. Ushbu misolda biz samolyot uchun qanotlarni yaratishimiz kerak - chap va o'ng. Keling, yarataylik!
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
}
Shunday qilib, biz sinf (samolyot) ichida statik bo'lmagan ichki sinf Wing(qanot) yaratdik Airplaneva ikkita o'zgaruvchini qo'shdik - chap qanot va o'ng qanot. Va har bir qanotning biz o'zgartirishimiz mumkin bo'lgan o'ziga xos xususiyatlari (rangi, modeli) bor. Shunday qilib, tuzilmalarni kerakli darajada xodimlar bilan ta'minlashingiz mumkin. Va e'tibor bering: ilgari diagrammada samolyot uchun juda ko'p qismlar mavjud edi va aslida biz barcha qismlarni ichki sinflarga ajratishimiz mumkin, ammo bunday jarayon har doim ham tavsiya etilmaydi. Bunday daqiqalarni vazifaga qarab kuzatish kerak. Muammoni hal qilish uchun sizga qanotlar kerak emas. Keyin ularni qilishning hojati yo'q. Bu odamni oyoqlari, qo'llari, tanasi va boshiga kesib tashlashga o'xshaydi - bu mumkin, lekin nima uchun bu sinf faqat odamlar haqidagi ma'lumotlarni saqlash uchun ishlatilsa? Statik bo'lmagan Java sinflarining xususiyatlari:
  1. Ular faqat ob'ektlarda mavjud, shuning uchun ularni yaratish uchun sizga ob'ekt kerak. Boshqacha qilib aytganda: biz qanotimizni samolyotning bir qismi bo'lishi uchun yaratdik, shuning uchun qanot yaratish uchun bizga samolyot kerak, aks holda bizga kerak emas.
  2. Java sinfida statik o'zgaruvchilar bo'lishi mumkin emas. Agar sizga doimiy yoki boshqa statik narsa kerak bo'lsa, ularni tashqi sinfga ko'chirishingiz kerak. Bu statik bo'lmagan ichki sinfning tashqi sinfga yaqin ulanishi bilan bog'liq.
  3. Sinf tashqi sinfning barcha shaxsiy maydonlariga to'liq kirish huquqiga ega. Bu xususiyat ikki usulda ishlaydi.
  4. Siz tashqi sinfning namunasiga havola olishingiz mumkin. Misol: Samolyot.bu samolyotga havola, bu qanotga havola.

Tashqi sinf ichidagi statik sinflar

Ushbu turdagi sinf oddiy tashqi sinfdan farq qilmaydi, faqat bitta narsadan tashqari: bunday sinfning namunasini yaratish uchun siz tashqi sinfdan kerakli yo'lni nuqta bilan ajratib ko'rsatishingiz kerak. Masalan: Building.Plaftorm platform = new Building.Platform(); Statik sinflar mantiqiy tuzilma bilan ishlashni osonlashtirishi uchun tegishli sinflarni yonma-yon joylashtirish uchun ishlatiladi. Misol uchun: biz tashqi sinf yaratishimiz mumkin Building, bu erda ma'lum bir binoni ifodalovchi sinflarning aniq ro'yxati bo'ladi.
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
}
Ushbu misol statik sinflar mantiqiy tuzilmani qulayroq shaklga to'plashga qanday imkon berishini ko'rsatadi. Agar ular mavjud bo'lmasa, biz 4 ta butunlay boshqa sinflarni yaratishimiz kerak edi. Ushbu yondashuvning afzalliklari:
  1. Darslar soni kamaydi.
  2. Barcha sinflar ota-onalar sinfida joylashgan. Biz har bir sinfni alohida ochmasdan butun ierarxiyani kuzatishimiz mumkin.
  3. Biz Building sinfiga murojaat qilishimiz mumkin va IDE allaqachon ushbu sinfning barcha quyi sinflarining to'liq ro'yxatini taklif qiladi. Bu sizga kerakli sinflarni topishni osonlashtiradi va butun rasmni yanada yaxlitroq ko'rsatadi.
Ichki statik sinfning namunasini yaratishga misol:Building.Shop myShop = new Building.Shop(“Food & Fun!”, “Kalyaeva 8/53”); Shuni ham ta'kidlashni istardimki, ushbu strategiya AWT 2D sinflarida Line2D, Arc2D, Ellipse2D va boshqalar kabi shakllarni tasvirlash uchun ishlatiladi.

Mahalliy sinflar

Bu sinflar boshqa usullar ichida e'lon qilinadi. Aslida, ular statik bo'lmagan ichki sinfning barcha xususiyatlariga ega, faqat ularning misollari faqat usulda yaratilishi mumkin va usul statik bo'lishi mumkin emas (ularni yaratish uchun sizga tashqi sinf namunasi, havola kerak. chaqiruvchi ob'ektning namunasi statik bo'lmagan usullarga bevosita uzatiladi va statik usulda bu havola uchun usul yo'q). Ammo ularning o'ziga xos xususiyatlari bor:
  1. Mahalliy sinflar faqat oxirgi usul o'zgaruvchilari bilan ishlashi mumkin. Gap shundaki, usul tugallangandan so'ng mahalliy sinflarning namunalari to'pda saqlanishi va o'zgaruvchini o'chirib tashlashi mumkin. Agar o'zgaruvchi yakuniy deb e'lon qilingan bo'lsa, kompilyator keyinchalik ob'ekt tomonidan foydalanish uchun o'zgaruvchining nusxasini saqlashi mumkin. Va yana bir narsa: Java-ning 8+ versiyalaridan beri siz mahalliy sinflarda yakuniy bo'lmagan o'zgaruvchilardan foydalanishingiz mumkin, lekin ular o'zgarmasligi sharti bilan.
  2. Mahalliy sinflarni kirish modifikatorlari bilan e'lon qilib bo'lmaydi.
  3. Mahalliy sinflar metod o'zgaruvchilariga kirish huquqiga ega.
Mahalliy sinflarni juda kamdan-kam hollarda topish mumkin, chunki ular kodni o'qishni qiyinlashtiradi va hech qanday afzalliklarga ega emas, faqat bitta - usul o'zgaruvchilarga kirish. Ulardan samarali foydalanishni ko'rsatadigan mahalliy sinfdan qanday misol olish mumkinligini bilmayman, shuning uchun men o'z misolimni ko'rsataman. Aytaylik, bizda mulk (ko'cha), (uy) bo'lgan sinf Person(bu odam deb taxmin qilinadi) bor. Biz faqat odamning joylashuviga kirish uchun ba'zi ob'ektni qaytarmoqchimiz. Buning uchun biz AddressContainer interfeysini yaratdik, bu odamning joylashuvi haqidagi ma'lumotlarni saqlashni nazarda tutadi. streethouse
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
}
Ko'rib turganingizdek, usul ichida biz odamning joylashuvini saqlashni amalga oshiradigan sinf yaratdik, u erda doimiy o'zgaruvchilar yaratdik (usuldan chiqqandan so'ng, o'zgaruvchilar ob'ektda saqlanadi) va manzilni olish usulini amalga oshirdik va uy. Endi biz ushbu ob'ektni dasturning boshqa joylarida odamning joylashuvini olish uchun ishlatishimiz mumkin. Men tushunamanki, bu misol ideal emas va buni sinfda qabul qiluvchilarni qoldirib qilish to'g'riroq bo'lardi Person, ammo bu sinfning yaratilishi va undan foydalanish mumkinligi ko'rsatilgan va keyin bu sizga bog'liq.

Anonim sinflar

Kaput ostida anonim sinflar oddiy statik bo'lmagan ichki o'rnatilgan sinflardir. Ularning o'ziga xosligi - ulardan foydalanish qulayligi. Boshqa sinfning namunasini yaratishda sinfingizni to'g'ridan-to'g'ri yozishingiz mumkin.
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!");
        }
    }
}
Aslini olganda, biz ikkita narsani bir joyda birlashtiramiz: bitta sinfning namunasini yaratish ( Animal) va uning merosxo'r ichki sinfining namunasini yaratish ( Tiger). Aks holda, biz sinfni alohida yaratishimiz va bir xil natijaga erishish uchun uzunroq konstruksiyalardan foydalanishimiz kerak. Anonim sinflardan foydalanish ko'p hollarda oqlanadi, xususan:
  • sinf tanasi juda qisqa;
  • sinfning faqat bitta nusxasi kerak;
  • sinf yaratilgan joyda yoki undan keyin darhol ishlatiladi;
  • Sinf nomi muhim emas va kodni tushunishni osonlashtirmaydi.
Anonim sinflar ko'pincha GUI-larda hodisa ishlov beruvchilarini yaratish uchun ishlatiladi. Masalan, tugma yaratish va uning bosilishiga munosabat bildirish uchun:
JButton b2 = new JButton("Click");
b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата!");
    }
});
Biroq, Java 8 dan keyin ular lambda iboralaridan foydalanishni boshladilar, lekin hali 8-versiyadan oldin juda ko'p kod yozilgan va siz bunday yozuvlarga duch kelishingiz mumkin (va JavaRush-da o'qiyotganingizda duch kelasiz).\ Lambdalar bilan analog:
JButton b2 = new JButton("Click");
b2.addActionListener(e -> System.out.println("Кнопка нажата!"));
Maqolaning oxiri E'tiboringiz uchun barchangizga rahmat va umid qilamanki, siz yangi narsalarni o'rgandingiz yoki ilgari tushunmagan narsani tushundingiz. Shuningdek, ushbu maqola "tafsilotlarga e'tibor berish" toifasiga tegishli ekanligini aniqlamoqchiman . Bu mening birinchi ishim, shuning uchun kimgadir foydali bo'ldi deb umid qilaman. Yaqin kunlarda yangi g'oyalar kelsa boshqa narsa yozishga harakat qilaman, faqat bitta fikr bor... Hammaga omad va dasturlashda muvaffaqiyat :)
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION