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.
Ushbu bo‘lim mundarijasi
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 #
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());
}
}
Husanboy Qodirov, 25 yosh
Baholar soni: 3
O'rtacha: 90.0
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:
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 + ")";
}
}
(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 xatopublic 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;
}
}
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.
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++;
}
}
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.
C# yoki Kotlin'dan farqli o'laroq, Java'da xossa (property) tushunchasi yo'q. Uning o'rniga oddiy metodlar yoziladi.
An'anaviy nom berish:
| Maqsad | An'anaviy nom | Misol |
|---|---|---|
| Qiymatni olish | getX() | getBalans() |
boolean olish | isX() | isFaol() |
| Qiymatni o'rnatish | setX() | 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 #
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 + ")";
}
}
Alpomish (yili noma'lum)
Alpomish (1928)
Noma'lum (yili noma'lum)
this(...) boshqa konstruktorni chaqiradi. U konstruktorning
birinchi ko'rsatmasi bo'lishi shart.
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 #
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 + "'}";
}
}
Sukut, '@' gacha: Oddiy
Qayta belgilangan: Chiroyli{nom='Namangan'}
toString() xesh kodni chiqaradiSystem.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 #
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;
}
}
Yaratilganlar soni: 3
Oxirgisi: Nodira
Doimiy: Jurnal v1
soni uchta obyekt uchun bitta - u sinfga tegishli, obyektga
emas.
| A'zo turi | Kimga tegishli | Chaqirish |
|---|---|---|
static maydon | Sinfga | Sinf.maydon |
| Oddiy maydon | Har bir obyektga | obyekt.maydon |
static final | Doimiy, BOSH HARFLAR bilan | Sinf.DOIMIY |
Kirish darajalari #
| Daraja | Kimga ko'rinadi |
|---|---|
public | Hammaga |
protected | Shu paket va vorislar |
| (yozilmagan) | Faqat shu paket - "paket darajasi" |
private | Faqat shu sinf ichida |
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 #
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;
}
}
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.
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.
Kitobsinfini yarating: nom, muallif, yil.- Maydonlarni
privateqilib, ularga metod orqali kirish bering. this.x = xni ataylabx = xdeb yozib, natijani ko'ring.- Uchta konstruktor yozib, ularni
this(...)bilan bog'lang. - Parametrli konstruktor qo'shgandan keyin
new Kitob()ishlamasligini tekshiring. toString()ni qayta belgilang va@Overrideqo'ying.@Overridedagi metod nomini ataylab xato yozing.statichisoblagich bilan yaratilgan obyektlar sonini sanang.static finaldoimiy e'lon qiling.- Ikki o'zgaruvchi bitta obyektga ishora qilishini tekshiring.
Xulosa #
- Java'da hamma narsa sinf ichida; bitta faylda faqat bitta
publicsinf bo'ladi. this.x = xni unutish jimginanullqoldiradi - 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@Overrideyozing.- Kirish darajasi to'rtta:
public,protected, paket darajasi,private. - Obyektlarni axlat yig'uvchi o'zi tozalaydi.
Keyingi bo'limda vorislik va interfeyslarni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.