1. record sinifinin genişləndirilməsi: əlavə metodlar
Record-a metodlar əlavə etmək olarmı?
Əlbəttə! Record hazır təmiri olan bir mənzil kimidir: divarlar və döşəmə artıq hazırdır, onları dəyişmək olmaz, amma mebeli özün bildiyin kimi düzəltməyə heç kim qadağa qoymur. record-un daxilində adi metodlar, statik metodlar elan etmək və hətta konstansiyalar saxlamaq olar. Bu o deməkdir ki, biznes məntiqini mütləq ayrıca «utilit» siniflərinə çıxarmağa ehtiyac yoxdur — onu səliqəli şəkildə elə record-un özünə daxil etmək olar.
Nümunə: nöqtələr arasında məsafənin hesablanması metodu
Tutaq ki, müstəvidə nöqtə üçün bir recordumuz var:
public record Point(int x, int y) {
// Əlavə metod
public double distanceTo(Point other) {
int dx = this.x - other.x;
int dy = this.y - other.y;
return Math.sqrt(dx * dx + dy * dy);
}
}
İndi bunu belə etmək olar:
Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
System.out.println(p1.distanceTo(p2)); // 5.0
Gördüyünüz kimi, record-sinifi öz metodlarınızla “zənginləşdirilə” bilər — bu çox rahatdır!
Nümunə: statik metod
public record Rectangle(int width, int height) {
public int area() {
return width * height;
}
public static Rectangle square(int size) {
return new Rectangle(size, size);
}
}
İndi «kvadrat»ı tək çağırışla yaratmaq olar:
Rectangle r = Rectangle.square(5);
System.out.println(r.area()); // 25
2. Kompakt konstruktor və verilənlərin validasiyası
«Kompakt» konstruktor nə üçün lazımdır?
Kanonik record-konstruktoru avtomatik yaradılır və parametrləri sahələrə təyin edir. Amma bəzən daxil olan məlumatları yoxlamaq istəyirik (məsələn, mənfi koordinatları qadağan etmək).
Adi sinifdə biz belə yazardıq:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
if (x < 0 || y < 0) throw new IllegalArgumentException();
this.x = x;
this.y = y;
}
// ...
}
record-sinifində kompakt konstruktor elan etmək olar — parametr siyahısını təkrarlamadan və sahələrə açıq təyinat yazmadan (bunları bizim yerimizə kompilyator edir).
Kompakt konstruktorun sintaksisi
public record Point(int x, int y) {
public Point {
if (x < 0 || y < 0) {
throw new IllegalArgumentException("Coordinates must be non-negative");
}
// Bunları yazmağa ehtiyac yoxdur: this.x = x; this.y = y;
}
}
- Konstruktorun parametrləri avtomatik olaraq komponentlərlə — record komponentləri ilə — üst-üstə düşür.
- this.x = x və this.y = y təyinatlarını kompilyator konstruktor bədəni icra olunduqdan (və ya ondan uğurla çıxıldıqdan) sonra avtomatik edir.
- Əgər istisna atılsa, obyekt yaradılmayacaq.
Yoxlama ilə nümunə
Point p1 = new Point(3, 5); // OK
Point p2 = new Point(-1, 2); // IllegalArgumentException atacaq!
«Adi» konstruktor elan etmək olarmı?
Bəli, olar! Əgər fərqli parametr siyahısı və ya əlavə məntiqi olan konstruktor yaratmaq lazımdırsa, onu açıq şəkildə elan edin:
public record Range(int from, int to) {
public Range(int size) {
this(0, size); // əsas konstruktoru çağırır
}
}
3. record-siniflərinin məhdudiyyətləri
Adi siniflərdən fərqli olaraq, record-siniflərin bir sıra məhdudiyyətləri var. Bunu xatırlamaq vacibdir ki, kompilyasiya xətalarına təəccüblənməyəsiniz.
Yalnız komponentlər — əlavə qeyri-statik sahələr yoxdur
record-sinifində yeni qeyri-statik sahələr elan etmək olmaz:
public record Person(String name, int age) {
// int id; // Kompilyasiya xətası! Qeyri-statik sahələr əlavə etmək olmaz.
}
Statik sahələr və metodlar elan etmək olar:
public record Person(String name, int age) {
public static final String SPECIES = "Homo sapiens";
}
Record həmişə final-dır
Record-sinif nə valideyn sinif ola bilər (ondan miras almaq olmaz), nə də özü başqa bir sinifdən açıq şəkildə miras ala bilər (qeyri-aşkar şəkildə java.lang.Record-dan miras almaqdan başqa). Bu o deməkdir ki, record-sinif — həmişə “son” strukturdur.
public record User(String login) { }
// public class Admin extends User {} // Xəta: record-dan irs almaq olmaz!
İnterfeysləri reallaşdırmaq olar
Record-sinif interfeysləri reallaşdıra bilər:
public interface Printable {
void print();
}
public record Invoice(int amount) implements Printable {
@Override
public void print() {
System.out.println("Məbləğ: " + amount);
}
}
4. Nümunələr: real tapşırıqlarda genişləndirilmiş record-lar
Gəlin bir neçə praktiki nümunəyə baxaq; burada əlavə metodlar və kompakt konstruktorlar record-sinifini həqiqətən faydalı edir.
Hesablayıcı metoda malik record
public record Circle(double x, double y, double radius) {
public double area() {
return Math.PI * radius * radius;
}
public double distanceTo(Circle other) {
double dx = x - other.x;
double dy = y - other.y;
return Math.sqrt(dx * dx + dy * dy);
}
}
Validasiyalı record
public record Email(String value) {
public Email {
if (value == null || !value.contains("@")) {
throw new IllegalArgumentException("Yanlış email: " + value);
}
}
}
İndi yanlış email yaratmaq olmaz:
Email e1 = new Email("test@example.com"); // OK
Email e2 = new Email("not-an-email"); // IllegalArgumentException atacaq
Əlavə statik metodları olan record
public record Temperature(double celsius) {
public static Temperature fromFahrenheit(double fahrenheit) {
return new Temperature((fahrenheit - 32) * 5 / 9);
}
public double toFahrenheit() {
return celsius * 9 / 5 + 32;
}
}
İstifadə:
Temperature t = Temperature.fromFahrenheit(98.6);
System.out.println(t.celsius()); // 37.0
System.out.println(t.toFahrenheit()); // 98.6
5. Kompakt konstruktor: incəliklər və məhdudiyyətlər
Kompakt konstruktordan nə vaxt istifadə etməli?
- Məlumatların düzgünlüyünü yoxlamaq (validasiya) lazım olanda.
- Saxlamadan əvvəl dəyərləri dəyişmək lazım olanda (məsələn, ədədi yuvarlaqlaşdırmaq və ya sətri böyük hərflərə çevirmək).
- Parametr siyahısının təkrarlanmasından qaçmaq istəyəndə.
İşləmə xüsusiyyətləri
- Kompakt konstruktorda komponentlərə açıq şəkildə dəyər təyin etmək olmaz (this.x = ...) — bu kompilyasiya xətasına səbəb olacaq, çünki kompilyator təyinatı konstruktor bədənindən sonra özü yerinə yetirir.
- Kompakt konstruktorda parametr adlarını dəyişmək olmaz — onlar həmişə record komponentlərinin adları ilə eynidir.
Nümunə: avtomatik yuvarlaqlaşdırma
public record Money(double amount) {
public Money {
amount = Math.round(amount * 100) / 100.0; // Məbləği qəpiyə qədər yuvarlaqlaşdırırıq
}
}
6. Təcrübə: tədris tətbiqini inkişaf etdiririk
Tutaq ki, biz tədris tətbiqində bank əməliyyatları hazırlayırıq. Gəlin record-sinif Transaction olsun; o, məbləği, göndərəni və alıcını saxlayır.
public record Transaction(String from, String to, double amount) {
public Transaction {
if (amount <= 0) throw new IllegalArgumentException("Məbləğ müsbət olmalıdır");
if (from == null || to == null) throw new IllegalArgumentException("Sahələr null ola bilməz");
}
public String description() {
return String.format("Köçürmə %.2f: %s → %s", amount, from, to);
}
}
İstifadə:
Transaction t = new Transaction("Alice", "Bob", 150.0);
System.out.println(t.description()); // Köçürmə 150.00: Alice → Bob
Yanlış tranzaksiya yaratmağa cəhd xəta yaradacaq:
Transaction t2 = new Transaction("Alice", "Bob", -10.0); // IllegalArgumentException
Cədvəl: record-sinifində nə olar və nə olmaz
| Record-sinifində olar | Record-sinifində olmaz |
|---|---|
| Adi metodlar | Yeni qeyri-statik sahələr |
| Statik metodlar və sahələr | Digər siniflərdən miras almaq |
| İnterfeysləri reallaşdırmaq | Başqa siniflər üçün superklass olmaq |
| Kompakt və adi konstruktorlar | Yaradıldıqdan sonra komponentləri dəyişmək |
| Metodları yenidən təyin etmək | Setter-lərdən istifadə etmək |
7. Standart olmayan bədənə malik record-siniflərlə işləyərkən tipik səhvlər
Səhv № 1: qeyri-statik sahə əlavə etmək cəhdi.
Yeni başlayanlar tez-tez record-sinifə “daxili məntiq üçün daha bir sahə” əlavə etməyə çalışırlar — məsələn, sayğac və ya keş. Bu işləməyəcək: kompilyator dərhal xəta verəcək. Əlavə vəziyyəti (state) saxlamaq lazımdırsa, çox güman, record-sinif düzgün seçim deyil.
Səhv № 2: kompakt konstruktorda validasiyanı unutmaq.
Obyektin həmişə düzgün olmasını istəyirsinizsə, yoxlamanı kompakt konstruktorda edin. “İstifadəçi özü səhv etməz” deyə arxayın olmayın.
Səhv № 3: yaradıldıqdan sonra komponenti dəyişmək cəhdi.
record-sinifin sahələri final-dır — onları nə birbaşa, nə də metodlar vasitəsilə dəyişmək olar. Dəyişən (mutable) struktur lazımdırsa — adi sinifdən istifadə edin.
Səhv № 4: məntiqin metodlarda və konstruktorda təkrarlanması.
Bəzən yoxlama məntiqini və hesablamaları həm metodlarda, həm də konstruktorda təkrarlayırlar. Daha yaxşısı, bütün validasiyanı konstruktorda edin, metodları isə “təmiz” biznes-məntiq üçün saxlayın.
Səhv № 5: irsiyyət məhdudiyyətlərini unutmaq.
Record-sinif həmişə final-dır — ondan törəmə yaratmaq olmaz. Əgər alt-siniflərə ehtiyac olan ierarxiya layihələndirirsinizsə — adi siniflərdən istifadə edin.
GO TO FULL VERSION