10-bo‘lim

Vorislik va interfeyslar

extends va super, metodni qayta belgilash, abstract sinflar, interfeyslar va default metodlar, polimorfizm hamda vorislik o'rniga kompozitsiya.

🕑 12 daqiqa o‘qish 📄 808 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Oddiy vorislik
  2. abstract sinf
  3. Interfeys
  4. default metodlar
  5. Bir nechta interfeys
  6. Interfeys yoki abstract sinf?
  7. Turni tekshirish
  8. Vorislik o'rniga kompozitsiya
  9. Xulosa

Vorislik - mavjud sinf asosida yangisini qurish. Interfeys esa "nima qila olishi" ni belgilaydigan shartnoma.

Oddiy vorislik #

Java
public class Vorislik {
    public static void main(String[] args) {
        new Talaba("Husanboy", 25, "Informatika").tanishtir();
        new Oqituvchi("Nodira", 40, "Matematika").tanishtir();
    }
}

class Shaxs {
    protected final String ism;
    protected final int yosh;

    Shaxs(String ism, int yosh) {
        this.ism = ism;
        this.yosh = yosh;
    }

    void tanishtir() {
        System.out.println("Men " + ism + ", " + yosh + " yoshdaman");
    }
}

class Talaba extends Shaxs {
    private final String yonalish;

    Talaba(String ism, int yosh, String yonalish) {
        super(ism, yosh);
        this.yonalish = yonalish;
    }

    @Override
    void tanishtir() {
        super.tanishtir();
        System.out.println("  " + yonalish + " yo'nalishi talabasiman");
    }
}

class Oqituvchi extends Shaxs {
    private final String fan;

    Oqituvchi(String ism, int yosh, String fan) {
        super(ism, yosh);
        this.fan = fan;
    }

    @Override
    void tanishtir() {
        System.out.println("Men " + ism + ", " + fan + " o'qituvchisiman");
    }
}
Natija
Men Husanboy, 25 yoshdaman
  Informatika yo'nalishi talabasiman
Men Nodira, Matematika o'qituvchisiman
Kalit so'zMa'nosi
extends ShaxsShu sinfdan meros oladi
super(...)Ota-ona konstruktorini chaqiradi
super.metod()Ota-ona versiyasini chaqiradi
@OverrideQayta belgilanayotganini bildiradi
protectedVorislar ko'radi, tashqaridagilar yo'q
super(...) birinchi bo'lishi shart

Voris konstruktorida super(...) eng birinchi ko'rsatma bo'lishi kerak.

Yozmasangiz, Java super() ni o'zi qo'shadi - ya'ni ota-onaning parametrsiz konstruktorini chaqiradi. Agar unday konstruktor bo'lmasa, kompilyatsiya xatosi chiqadi:

Natija
error: constructor Shaxs in class Shaxs cannot be applied
to given types

Bu yangi boshlovchilar tez-tez uchraydigan holat: ota-onada faqat parametrli konstruktor bor, vorisda esa super(...) yozilmagan.

Java'da metodlar sukut bo'yicha qayta yoziladi

Bu C# dan muhim farq. C# da metodni virtual deb belgilash kerak, Java'da esa hamma metod avtomatik qayta yozilishi mumkin.

Qayta yozishni taqiqlash uchun final yoziladi:

Java
class Asos {
    final void ozgarmas() { }
}

Bu shuni anglatadiki, Java'da sinf yozganingizda vorislar har qanday metodni o'zgartirishi mumkin - siz buni rejalashtirmagan bo'lsangiz ham. Shuning uchun vorislikka mo'ljallanmagan sinflarni final deb belgilash yaxshi amaliyot.

abstract sinf #

Java
public class Shakllar {
    public static void main(String[] args) {
        Shakl[] shakllar = {new Doira(5), new Togritortburchak(4, 6)};

        for (Shakl shakl : shakllar) {
            System.out.printf("%-16s maydoni = %.2f%n",
                    shakl.nomi(), shakl.maydon());
        }
    }
}

abstract class Shakl {
    abstract String nomi();

    abstract double maydon();
}

class Doira extends Shakl {
    private final double radius;

    Doira(double radius) {
        this.radius = radius;
    }

    @Override
    String nomi() {
        return "Doira";
    }

    @Override
    double maydon() {
        return Math.PI * radius * radius;
    }
}

class Togritortburchak extends Shakl {
    private final double eni;
    private final double boyi;

    Togritortburchak(double eni, double boyi) {
        this.eni = eni;
        this.boyi = boyi;
    }

    @Override
    String nomi() {
        return "To'rtburchak";
    }

    @Override
    double maydon() {
        return eni * boyi;
    }
}
Natija
Doira            maydoni = 78.54
To'rtburchak     maydoni = 24.00

abstract sinfdan obyekt yaratib bo'lmaydi; abstract metodning tanasi yo'q va voris uni albatta amalga oshirishi shart.

Bu polimorfizm

Sikl Shakl turi bilan ishlaydi, lekin har bir element uchun o'zining maydon() metodi chaqirildi.

Kod qaysi aniq shakl kelishini bilmaydi. Yangi shakl qo'shsangiz - masalan uchburchak - bu siklni umuman o'zgartirish kerak emas.

Bu obyektga yo'naltirilgan dasturlashning asosiy foydasi.

Diqqat: printf da %n ishlatilgan, \n emas. %n har bir tizimga mos qator uzilishini qo'yadi - Windows'da \r\n, Linux'da \n. Ko'chma kod uchun shu afzal.

Interfeys #

Java
import java.util.ArrayList;
import java.util.List;

public class Interfeyslar {
    public static void main(String[] args) {
        Yozuvchi[] chiqishlar = {new Konsolga(), new Xotiraga()};

        for (Yozuvchi y : chiqishlar) {
            y.yoz("Salom");
            y.yoz("Dunyo");
        }

        for (Yozuvchi y : chiqishlar) {
            if (y instanceof Xotiraga x) {
                x.korsat();
            }
        }
    }
}

interface Yozuvchi {
    void yoz(String matn);

    default void yozKatta(String matn) {
        yoz(matn.toUpperCase());
    }
}

class Konsolga implements Yozuvchi {
    @Override
    public void yoz(String matn) {
        System.out.println("[konsol] " + matn);
    }
}

class Xotiraga implements Yozuvchi {
    private final List<String> qatorlar = new ArrayList<>();

    @Override
    public void yoz(String matn) {
        qatorlar.add(matn);
    }

    void korsat() {
        System.out.println("[xotira] " + qatorlar.size()
                + " qator: " + String.join(", ", qatorlar));
    }
}
Natija
[konsol] Salom
[konsol] Dunyo
[xotira] 2 qator: Salom, Dunyo
Interfeys metodlari avtomatik public

Interfeysdagi metodlar sukut bo'yicha public abstract hisoblanadi.

Shuning uchun ularni amalga oshirganda public yozish majburiy - aks holda kirish darajasi torayadi va kompilyator xato beradi:

Natija
error: yoz(String) in Konsolga cannot implement yoz(String)
in Yozuvchi; attempting to assign weaker access privileges

Bu juda ko'p uchraydigan xato: sinf metodlarida public yozmaslikka odatlangan dasturchi interfeysni amalga oshirganda ham unutadi.

default metodlar #

Java 8 dan interfeysda tayyor kod ham bo'lishi mumkin:

Java
public class Default {
    public static void main(String[] args) {
        Salomlovchi s = ism -> System.out.println("Salom, " + ism);

        s.salomlash("Husanboy");
        s.salomlashRasmiy("Nodira Karimovna");
    }
}

interface Salomlovchi {
    void salomlash(String ism);

    default void salomlashRasmiy(String ism) {
        salomlash("hurmatli " + ism);
    }
}
Natija
Salom, Husanboy
Salom, hurmatli Nodira Karimovna
default nima uchun qo'shilgan

Java 8 da List interfeysiga forEach va stream metodlari qo'shildi.

Muammo: dunyodagi minglab sinf List ni amalga oshirgan edi. Yangi metod qo'shilsa, ularning hammasi buzilardi.

default shu muammoni hal qildi: interfeysga tayyor tanali metod qo'shish mumkin bo'ldi va mavjud sinflar o'zgarishsiz ishlashda davom etdi.

Ya'ni default - avvalo moslikni saqlash vositasi. Undan o'zingizning interfeyslaringizda ehtiyotkorlik bilan foydalaning.

Bir nechta interfeys #

Sinf bitta sinfdan meros oladi, lekin istalgancha interfeysni amalga oshirishi mumkin:

Java
public class KopInterfeys {
    public static void main(String[] args) {
        Hujjat h = new Hujjat("Hisobot");
        h.saqla();
        h.chop();
    }
}

interface Saqlanadigan {
    void saqla();
}

interface ChopEtiladigan {
    void chop();
}

class Hujjat implements Saqlanadigan, ChopEtiladigan {
    private final String nom;

    Hujjat(String nom) {
        this.nom = nom;
    }

    @Override
    public void saqla() {
        System.out.println(nom + " saqlandi");
    }

    @Override
    public void chop() {
        System.out.println(nom + " chop etildi");
    }
}
Natija
Hisobot saqlandi
Hisobot chop etildi
Nega faqat bitta sinfdan meros?

Bir nechta sinfdan meros olish "olmos muammosi" ni keltirib chiqaradi: ikkita ota-onada bir xil nomli metod bo'lsa, qaysi biri ishlashi noaniq bo'lib qoladi.

C++ da bu mumkin va shu sababli murakkab qoidalar kerak. Java bu yo'ldan bormaslikka qaror qilgan: bitta sinf, istalgancha interfeys.

default metodlar paydo bo'lgach, muammo qisman qaytdi - ikkita interfeysda bir xil nomli default metod bo'lsa, sinf uni majburan qayta belgilashi kerak. Kompilyator buni talab qiladi.

Interfeys yoki abstract sinf? #

InterfeysAbstract sinf
Nechtasini olish mumkinIstalganchaBittasini
Maydon saqlay oladimiFaqat static finalHa
KonstruktorYo'qHa
Tayyor koddefault metodlarHa, to'liq
Qachon"Nima qila oladi""Nima ekanligi"

Qoida: "bu shunday qila oladi" desangiz - interfeys (Yozuvchi). "bu shunday narsa" desangiz - abstract sinf (Shakl).

Turni tekshirish #

Java
public class Tekshirish {
    public static void main(String[] args) {
        Object[] narsalar = {new Doira(2), new Kvadrat(3), "matn"};

        for (Object narsa : narsalar) {
            if (narsa instanceof Shakl shakl) {
                System.out.printf("Shakl, maydoni %.2f%n", shakl.maydon());
            } else {
                System.out.println("Shakl emas: "
                        + narsa.getClass().getSimpleName());
            }
        }
    }
}

abstract class Shakl {
    abstract double maydon();
}

class Doira extends Shakl {
    private final double r;

    Doira(double r) {
        this.r = r;
    }

    @Override
    double maydon() {
        return Math.PI * r * r;
    }
}

class Kvadrat extends Shakl {
    private final double t;

    Kvadrat(double t) {
        this.t = t;
    }

    @Override
    double maydon() {
        return t * t;
    }
}
Natija
Shakl, maydoni 12.57
Shakl, maydoni 9.00
Shakl emas: String

Vorislik o'rniga kompozitsiya #

"Meros" munosabatni to'g'ri tekshiring

Vorislik faqat "A - bu B ning turi" bo'lganda to'g'ri:

  • Talaba - bu Shaxs ning turi. To'g'ri.
  • Kvadrat - bu Shakl ning turi. To'g'ri.
  • Avtomobil - bu Dvigatel ning turi? Yo'q. Avtomobilda dvigatel bor.

Ikkinchi holatda vorislik emas, kompozitsiya kerak:

Java
public class Kompozitsiya {
    public static void main(String[] args) {
        new Avtomobil("Nexia").yur();
    }
}

class Dvigatel {
    String ishga() {
        return "dvigatel ishga tushdi";
    }
}

class Avtomobil {
    private final String nom;
    private final Dvigatel dvigatel = new Dvigatel();

    Avtomobil(String nom) {
        this.nom = nom;
    }

    void yur() {
        System.out.println(nom + ": " + dvigatel.ishga());
    }
}
Natija
Nexia: dvigatel ishga tushdi

Bu moslashuvchanroq: dvigatelni keyin boshqasiga almashtirish mumkin, Avtomobil esa o'zgarmaydi.

Amaliy qoida: avval kompozitsiyani o'ylang, vorislikni faqat haqiqatan "bu shuning turi" bo'lganda ishlating.

Amaliy topshiriq
  1. Shaxs sinfidan Talaba va Oqituvchi ni meros oling.
  2. super(...) ni olib tashlab, kompilyator nima deyishini ko'ring.
  3. Metodni final qilib, vorisda qayta yozishga urinib ko'ring.
  4. abstract Shakl sinfi va uchta vorisini yozing.
  5. Ularni bitta massivga solib, siklda maydonlarini chiqaring.
  6. Interfeysni amalga oshirganda public ni unutib, xatoni ko'ring.
  7. default metodli interfeys yozing.
  8. Bitta sinfda ikkita interfeysni amalga oshiring.
  9. instanceof bilan turni tekshirib, xavfsiz aylantiring.
  10. Avtomobil va Dvigatel misolida kompozitsiyani qo'llang.

Xulosa #

  • Vorislik extends, interfeys implements bilan yoziladi.
  • super(...) voris konstruktorining birinchi ko'rsatmasi bo'lishi shart.
  • Java'da metodlar sukut bo'yicha qayta yoziladi; taqiqlash uchun final.
  • @Override ni har doim yozing - nom xato bo'lsa kompilyator aytadi.
  • abstract sinfdan obyekt yaratib bo'lmaydi.
  • Interfeys metodlarini amalga oshirganda public majburiy.
  • default metodlar mavjud kodni buzmasdan interfeysni kengaytirish uchun qo'shilgan.
  • printf da %n ishlating, \n emas.
  • Munosabat "bu shuning turi" bo'lmasa - kompozitsiya.

Keyingi bo'limda record, enum va yopiq sinflarni ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.