9-bo‘lim

Sinflar va obyektlar

Sinf e'lon qilish, maydonlar va konstruktorlar, this, inkapsulyatsiya va getter'lar, static a'zolar, toString va obyektning hayot davri.

🕑 12 daqiqa o‘qish 📄 877 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Birinchi sinf
  2. this
  3. Inkapsulyatsiya
  4. Konstruktorlar
  5. toString
  6. static a'zolar
  7. Kirish darajalari
  8. Obyektning hayot davri
  9. Xulosa

Sinf - o'zingiz yaratadigan tur. U ma'lumot (maydonlar) va shu ma'lumot ustidagi amallarni (metodlar) bir joyga jamlaydi.

Java'da hamma narsa sinf ichida bo'ladi, shuning uchun bu bo'lim tilning markazi.

Birinchi sinf #

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

public class Jurnal {
    public static void main(String[] args) {
        Talaba t = new Talaba("Husanboy Qodirov", 25);

        t.ballQoshish(90);
        t.ballQoshish(85);
        t.ballQoshish(95);

        t.korsat();
    }
}

class Talaba {
    private final String ism;
    private final int yosh;
    private final List<Integer> ballar = new ArrayList<>();

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

    void ballQoshish(int ball) {
        ballar.add(ball);
    }

    double ortacha() {
        if (ballar.isEmpty()) {
            return 0;
        }
        int jami = 0;
        for (int b : ballar) {
            jami += b;
        }
        return (double) jami / ballar.size();
    }

    void korsat() {
        System.out.println(ism + ", " + yosh + " yosh");
        System.out.println("Baholar soni: " + ballar.size());
        System.out.println("O'rtacha: " + ortacha());
    }
}
Natija
Husanboy Qodirov, 25 yosh
Baholar soni: 3
O'rtacha: 90.0
Bitta faylda ikkita sinf

Diqqat qiling: Talaba sinfi public emas. Java'da bitta faylda faqat bitta public sinf bo'lishi mumkin va uning nomi fayl nomiga mos bo'lishi shart.

Qolgan sinflar public siz yozilsa, bir faylda bo'lishi mumkin. Bu darslikdagi misollarni qisqa qilish uchun shunday qilingan.

Haqiqiy loyihada har bir sinf o'z faylida va odatda public bo'ladi: Talaba.java, Jurnal.java.

this #

this - "shu obyekt" degani. U ikki joyda kerak:

Java
public class ThisMisol {
    public static void main(String[] args) {
        Nuqta n = new Nuqta(3, 4);
        System.out.println(n.korsat());
        System.out.println(n.siljit(1, 1).korsat());
    }
}

class Nuqta {
    private final int x;
    private final int y;

    Nuqta(int x, int y) {
        this.x = x;          // maydon = parametr
        this.y = y;
    }

    Nuqta siljit(int dx, int dy) {
        return new Nuqta(this.x + dx, this.y + dy);
    }

    String korsat() {
        return "(" + x + ", " + y + ")";
    }
}
Natija
(3, 4)
(4, 5)

Konstruktorda parametr va maydon nomi bir xil - this.x maydon, oddiy x esa parametr. Usiz x = x yozilardi va bu hech narsa qilmasdi.

this.x = x ni unutish - jimgina xato
Java
public class Unutilgan {
    public static void main(String[] args) {
        Odam o = new Odam("Malika");
        System.out.println("Ism: " + o.ism());
    }
}

class Odam {
    private String ism;

    Odam(String ism) {
        ism = ism;           // XATO: parametr o'ziga o'zlashtirildi
    }

    String ism() {
        return ism;
    }
}
Natija
Ism: null

Kompilyator xato bermaydi - ism = ism sintaktik jihatdan to'g'ri. Lekin maydon o'rnatilmay qoladi va null bo'lib qoladi.

Yechim: this.ism = ism;. IDE bunday holatda odatda ogohlantiradi, shuning uchun IDE ishlatish foydali.

Inkapsulyatsiya #

Maydonlarni yashirib, ularga nazorat ostida kirish berish - obyektga yo'naltirilgan dasturlashning asosiy qoidasi.

Java
public class Bank {
    public static void main(String[] args) {
        Hisob h = new Hisob("Malika");

        h.qoshish(50000);
        h.qoshish(30000);
        h.yechish(20000);
        h.yechish(999999);

        System.out.println(h.egasi() + ": " + h.balans() + " so'm");
        System.out.println("Amallar soni: " + h.amallarSoni());
    }
}

class Hisob {
    private final String egasi;
    private long balans = 0;
    private int amallar = 0;

    Hisob(String egasi) {
        this.egasi = egasi;
    }

    String egasi() {
        return egasi;
    }

    long balans() {
        return balans;
    }

    int amallarSoni() {
        return amallar;
    }

    void qoshish(long miqdor) {
        if (miqdor <= 0) {
            throw new IllegalArgumentException("Miqdor musbat bo'lsin");
        }
        balans += miqdor;
        amallar++;
    }

    void yechish(long miqdor) {
        if (miqdor > balans) {
            System.out.println("Mablag' yetarli emas: " + miqdor);
            return;
        }
        balans -= miqdor;
        amallar++;
    }
}
Natija
Mablag' yetarli emas: 999999
Malika: 60000 so'm
Amallar soni: 3

balans ni tashqaridan o'zgartirib bo'lmaydi - faqat qoshish va yechish orqali, va ular tekshiruv o'tkazadi.

Java'da xossa yo'q

C# yoki Kotlin'dan farqli o'laroq, Java'da xossa (property) tushunchasi yo'q. Uning o'rniga oddiy metodlar yoziladi.

An'anaviy nom berish:

MaqsadAn'anaviy nomMisol
Qiymatni olishgetX()getBalans()
boolean olishisX()isFaol()
Qiymatni o'rnatishsetX()setIsm(...)

Bu darslikda qisqalik uchun balans() kabi qisqa nomlar ishlatilgan - bu record uslubidagi zamonaviy yondashuv.

Haqiqiy loyihada, ayniqsa Spring yoki boshqa freymvork bilan ishlaganda, getX() / setX() shakli kerak bo'ladi: ko'p kutubxona aynan shu nomlarni qidiradi.

Konstruktorlar #

Java
public class Konstruktorlar {
    public static void main(String[] args) {
        System.out.println(new Kitob("Alpomish").tavsif());
        System.out.println(new Kitob("Alpomish", 1928).tavsif());
        System.out.println(new Kitob().tavsif());
    }
}

class Kitob {
    private final String nom;
    private final int yili;

    Kitob() {
        this("Noma'lum", 0);
    }

    Kitob(String nom) {
        this(nom, 0);
    }

    Kitob(String nom, int yili) {
        this.nom = nom;
        this.yili = yili;
    }

    String tavsif() {
        return yili == 0 ? nom + " (yili noma'lum)" : nom + " (" + yili + ")";
    }
}
Natija
Alpomish (yili noma'lum)
Alpomish (1928)
Noma'lum (yili noma'lum)

this(...) boshqa konstruktorni chaqiradi. U konstruktorning birinchi ko'rsatmasi bo'lishi shart.

Sukut konstruktori

Agar sinfda hech qanday konstruktor yozmasangiz, Java bo'sh konstruktorni o'zi qo'shadi.

Lekin bitta konstruktor yozsangiz, sukut konstruktori yo'qoladi. Shuning uchun yuqoridagi misolda Kitob() ni oshkora yozish kerak bo'ldi.

Bu ko'p uchraydigan xato manbai: parametrli konstruktor qo'shgandan keyin new Kitob() to'satdan ishlamay qoladi.

toString #

Java
public class ToStringMisol {
    public static void main(String[] args) {
        String sukut = new Oddiy().toString();

        System.out.println("Sukut, '@' gacha: "
                + sukut.substring(0, sukut.indexOf('@')));
        System.out.println("Qayta belgilangan: " + new Chiroyli("Namangan"));
    }
}

class Oddiy {
}

class Chiroyli {
    private final String nom;

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

    @Override
    public String toString() {
        return "Chiroyli{nom='" + nom + "'}";
    }
}
Natija
Sukut, '@' gacha: Oddiy
Qayta belgilangan: Chiroyli{nom='Namangan'}
Sukut toString() xesh kodni chiqaradi

System.out.println(new Oddiy()) yozsangiz, Oddiy@2a139a55 kabi narsa chiqadi. @ dan keyingi raqam - obyektning xesh kodi va u har ishga tushirishda o'zgaradi.

Aynan shuning uchun yuqoridagi misol faqat @ gacha bo'lgan qismni chop etadi - aks holda bu darslikdagi kutilgan natijani yozib bo'lmasdi.

7-bo'limdagi qoida shu yerda ham amal qiladi: bunday chiqishni hech qachon solishtirmang.

Sukut toString() foydasiz, shuning uchun o'z sinflaringizda uni har doim qayta belgilang - nosozliklarni qidirishda bu juda yordam beradi.

@Override izohi majburiy emas, lekin uni yozing: agar metod nomini xato yozsangiz, kompilyator darhol xato beradi.

static a'zolar #

Java
public class Statik {
    public static void main(String[] args) {
        new Foydalanuvchi("Husanboy");
        new Foydalanuvchi("Malika");
        Foydalanuvchi oxirgi = new Foydalanuvchi("Nodira");

        System.out.println("Yaratilganlar soni: " + Foydalanuvchi.soni());
        System.out.println("Oxirgisi: " + oxirgi.ism());
        System.out.println("Doimiy: " + Foydalanuvchi.TIZIM);
    }
}

class Foydalanuvchi {
    static final String TIZIM = "Jurnal v1";
    private static int soni = 0;

    private final String ism;

    Foydalanuvchi(String ism) {
        this.ism = ism;
        soni++;
    }

    String ism() {
        return ism;
    }

    static int soni() {
        return soni;
    }
}
Natija
Yaratilganlar soni: 3
Oxirgisi: Nodira
Doimiy: Jurnal v1

soni uchta obyekt uchun bitta - u sinfga tegishli, obyektga emas.

A'zo turiKimga tegishliChaqirish
static maydonSinfgaSinf.maydon
Oddiy maydonHar bir obyektgaobyekt.maydon
static finalDoimiy, BOSH HARFLAR bilanSinf.DOIMIY

Kirish darajalari #

DarajaKimga ko'rinadi
publicHammaga
protectedShu paket va vorislar
(yozilmagan)Faqat shu paket - "paket darajasi"
privateFaqat shu sinf ichida
Java'da to'rtta daraja bor

Ko'pchilik uchtasini biladi, lekin to'rttasi bor: hech narsa yozmasangiz, bu "paket darajasi" (package-private) bo'ladi va a'zo faqat shu paketdagi sinflarga ko'rinadi.

Bu C# dagi internal ga o'xshaydi, lekin qamrovi torroq - loyiha emas, paket.

Amaliy qoida: maydonlar private, tashqariga kerak bo'lgan metodlar public, qolgani sukut holatda.

Obyektning hayot davri #

Java
public class Hayot {
    public static void main(String[] args) {
        Hisoblagich a = new Hisoblagich();
        Hisoblagich b = a;              // yangi obyekt EMAS

        a.oshir();
        b.oshir();

        System.out.println("a: " + a.qiymat());
        System.out.println("b: " + b.qiymat());
        System.out.println("Bitta obyektmi: " + (a == b));

        Hisoblagich c = new Hisoblagich();
        System.out.println("c alohida: " + c.qiymat());
    }
}

class Hisoblagich {
    private int soni = 0;

    void oshir() {
        soni++;
    }

    int qiymat() {
        return soni;
    }
}
Natija
a: 2
b: 2
Bitta obyektmi: true
c alohida: 0

Hisoblagich b = a yangi obyekt yaratmaydi - u mavjud obyektga ikkinchi nom beradi. 3-bo'limdagi havola qoidasi.

Obyektlarni kim o'chiradi

Java'da obyektni qo'lda o'chirish kerak emas - unga hech qanday havola qolmaganda axlat yig'uvchi (garbage collector) uni o'zi tozalaydi.

delete yoki free kabi buyruq yo'q. C va C++ dagi eng ko'p uchraydigan xatolar sinfi - xotira sizishi va bo'shatilgan xotiraga murojaat - Java'da deyarli uchramaydi.

Buning evaziga: axlat yig'uvchi qachon ishlashini siz boshqara olmaysiz va u ishlaganda dastur qisqa vaqtga to'xtashi mumkin.

Amaliy topshiriq
  1. Kitob sinfini yarating: nom, muallif, yil.
  2. Maydonlarni private qilib, ularga metod orqali kirish bering.
  3. this.x = x ni ataylab x = x deb yozib, natijani ko'ring.
  4. Uchta konstruktor yozib, ularni this(...) bilan bog'lang.
  5. Parametrli konstruktor qo'shgandan keyin new Kitob() ishlamasligini tekshiring.
  6. toString() ni qayta belgilang va @Override qo'ying.
  7. @Override dagi metod nomini ataylab xato yozing.
  8. static hisoblagich bilan yaratilgan obyektlar sonini sanang.
  9. static final doimiy e'lon qiling.
  10. Ikki o'zgaruvchi bitta obyektga ishora qilishini tekshiring.

Xulosa #

  • Java'da hamma narsa sinf ichida; bitta faylda faqat bitta public sinf bo'ladi.
  • this.x = x ni unutish jimgina null qoldiradi - kompilyator ogohlantirmaydi.
  • Maydonlar private, tashqariga metod orqali chiqariladi.
  • Java'da xossa yo'q - an'anaviy getX() / setX() metodlari yoziladi.
  • Parametrli konstruktor yozsangiz, sukut konstruktori yo'qoladi.
  • this(...) boshqa konstruktorni chaqiradi va birinchi ko'rsatma bo'lishi shart.
  • toString() ni har doim qayta belgilang va @Override yozing.
  • Kirish darajasi to'rtta: public, protected, paket darajasi, private.
  • Obyektlarni axlat yig'uvchi o'zi tozalaydi.

Keyingi bo'limda vorislik va interfeyslarni o'rganamiz.

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.