-
Sadrazamv4
instagram:sadrazam.spy Tg:Sadrazamv4
🚀 BAŞTAN SONA RUST DİLİ BÖLÜM-12: Traits (Nitelikler) ve Arayüz Yönetimi 🛡️
Selamlar! Serimizin 12. bölümüne hoş geldiniz.
Önceki bölümde esnek ve türden bağımsız kod yazmamızı sağlayan Generics (Jenerikler) konusunu incelemiştik. Bu bölümde ise Rust'ın Nesne Yönelimli Programlamadaki (OOP) "Interface" (Arayüz) yapısına karşılık gelen ve dildeki polimorfizmin (çok biçimlilik) temelini oluşturan **Traits (Nitelikler)** konusunu işleyeceğiz.
Trait, farklı tiplerin ortaklaşa paylaşabileceği bir davranışı (behavior) tanımlar.
---
📌 1. Trait Nedir ve Nasıl Tanımlanır? 🛠️
Bir Trait, bir veya birden fazla metodun imzasını (signature) içerir. Bu metoda sahip olmak isteyen tipler, bu Trait'i implemente etmek (uygulamak) zorundadır.
Örnek: Bir haber özetleme sistemi tasarlayalım.
pub trait Ozetlenebilir {
fn ozet_cikar(&self) -> String;
}
Burada `Ozetlenebilir` adında bir Trait tanımladık. Bu Trait'i uygulayan her tip, geriye `String` döndüren bir `ozet_cikar` metodu yazmak ZORUNDADIR.
---
🏗️ 2. Trait'i Bir Tipe Uygulamak (`impl Trait for Struct`) 🧱
Tanımladığımız Trait'i farklı Struct yapılarımıza uygulayalım:
pub struct Haber {
pub baslik: String,
pub konum: String,
pub yazar: String,
pub icerik: String,
}
impl Ozetlenebilir for Haber {
fn ozet_cikar(&self) -> String {
format!("{}, yazar: {} ({})", self.baslik, self.yazar, self.konum)
}
}
pub struct Tweet {
pub kullanici_adi: String,
pub icerik: String,
pub yanit_mi: bool,
pub retweet_mi: bool,
}
impl Ozetlenebilir for Tweet {
fn ozet_cikar(&self) -> String {
format!("{}: {}", self.kullanici_adi, self.icerik)
}
}
fn main() {
let tweet = Tweet {
kullanici_adi: String::from("rust_dev"),
icerik: String::from("Rust Trait sistemi muazzam! 🦀"),
yanit_mi: false,
retweet_mi: false,
};
println!("Yeni tweet: {}", tweet.ozet_cikar());
}
---
💡 3. Varsayılan Metot İmplementasyonu (Default Implementation) ⚙️
Trait içinde metodun sadece imzasını değil, varsayılan bir gövde (default body) de yazabilirsiniz. Eğer uygulayan Struct bu metodu ezmezse (override), varsayılan kod çalışır.
pub trait Ozetlenebilir {
fn ozet_cikar(&self) -> String {
String::from("(Devamını oku...)") // Varsayılan davranış
}
}
// Eğer Struct içinde 'impl Ozetlenebilir for Haber {}' yazıp içi boş bırakılırsa,
// varsayılan 'ozet_cikar' metodu geçerli olur!
---
🎯 4. Parametre Olarak Trait Kullanımı: `impl Trait` 🎯
Bir fonksiyona parametre olarak "Belirli bir Trait'i uygulayan herhangi bir tip" geçirebiliriz.
pub fn ozeti_yazdir(oge: &impl Ozetlenebilir) {
println!("Haber Özeti: {}", oge.ozet_cikar());
}
Bu fonksiyon; `Haber`, `Tweet` veya `Ozetlenebilir` Trait'ine sahip başka herhangi bir Struct örneğini parametre olarak alabilir!
---
🚧 5. Trait Bounds (Trait Kısıtlamaları) ve `where` Cümlesi ⛓️
`impl Trait` syntax'ı aslında **Trait Bound** yapısının kısa yazımıdır. Karmaşık durumlarda Trait Bound ve `where` kelimesi okunabilirliği ciddi oranda artırır.
### Uzun Trait Bound Yazımı:
pub fn bildirim_gonder<T: Ozetlenebilir>(item1: &T, item2: &T) {
println!("Bildirim: {}", item1.ozet_cikar());
}
### Birden Fazla Trait Şartı (`+` Operatörü):
`T` tipinin hem `Ozetlenebilir` hem de `Display` Trait'ini uygulamasını isteyebiliriz:
pub fn detayli_yazdir<T: Ozetlenebilir + std::fmt:
isplay>(item: &T) { ... }
### `where` Cümlesi İle Temiz Kod:
Birden fazla jenerik parametre ve kısıtlama olduğunda imza kirlenir. `where` bunu çözer:
// Okunması zor yazım:
fn fonksiyon<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 { ... }
// 'where' ile temiz yazım:
fn fonksiyon<T, U>(t: &T, u: &U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{
// Fonksiyon gövdesi
}
---
↩️ 6. Dönüş Tipi Olarak Trait: `returns impl Trait` 🔄
Bir fonksiyonun belirli bir Trait'i uygulayan anonim bir tip döndürmesini sağlayabiliriz:
fn rastgele_yazar_olustur() -> impl Ozetlenebilir {
Tweet {
kullanici_adi: String::from("anonim"),
icerik: String::from("Kod yazmaya devam!"),
yanit_mi: false,
retweet_mi: false,
}
}
⚠️ **Kısıtlama:** `impl Trait` dönüş tipinde, fonksiyon gövdesinden YALNIZCA TEK BİR somut tip dönebilir. Koşula göre (`if/else`) hem `Tweet` hem `Haber` döndüremezsiniz! (İleride `Box<dyn Trait>` ile bu kısıtlamayı aşmayı göreceğiz).
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Trait kavramını, `impl Trait for Struct` yapısını, varsayılan metotları, Trait Bound kısıtlamalarını ve `where` cümlesini inceledik.
👉 **Bölüm 13'te Bizi Ne Bekliyor?**
• Rust'ın Referans Güvenliği: **Lifetimes (Yaşam Süreleri)** ⏳
• Borrow Checker mekanizması ve Dangling Pointer önleme
• Lifetime Annotations
(`'a`, `'static`)
• Struct ve Fonksiyonlarda Lifetime kullanımı
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! 🦀✨
Selamlar! Serimizin 12. bölümüne hoş geldiniz.
Önceki bölümde esnek ve türden bağımsız kod yazmamızı sağlayan Generics (Jenerikler) konusunu incelemiştik. Bu bölümde ise Rust'ın Nesne Yönelimli Programlamadaki (OOP) "Interface" (Arayüz) yapısına karşılık gelen ve dildeki polimorfizmin (çok biçimlilik) temelini oluşturan **Traits (Nitelikler)** konusunu işleyeceğiz.
Trait, farklı tiplerin ortaklaşa paylaşabileceği bir davranışı (behavior) tanımlar.
---
📌 1. Trait Nedir ve Nasıl Tanımlanır? 🛠️
Bir Trait, bir veya birden fazla metodun imzasını (signature) içerir. Bu metoda sahip olmak isteyen tipler, bu Trait'i implemente etmek (uygulamak) zorundadır.
Örnek: Bir haber özetleme sistemi tasarlayalım.
pub trait Ozetlenebilir {
fn ozet_cikar(&self) -> String;
}
Burada `Ozetlenebilir` adında bir Trait tanımladık. Bu Trait'i uygulayan her tip, geriye `String` döndüren bir `ozet_cikar` metodu yazmak ZORUNDADIR.
---
🏗️ 2. Trait'i Bir Tipe Uygulamak (`impl Trait for Struct`) 🧱
Tanımladığımız Trait'i farklı Struct yapılarımıza uygulayalım:
pub struct Haber {
pub baslik: String,
pub konum: String,
pub yazar: String,
pub icerik: String,
}
impl Ozetlenebilir for Haber {
fn ozet_cikar(&self) -> String {
format!("{}, yazar: {} ({})", self.baslik, self.yazar, self.konum)
}
}
pub struct Tweet {
pub kullanici_adi: String,
pub icerik: String,
pub yanit_mi: bool,
pub retweet_mi: bool,
}
impl Ozetlenebilir for Tweet {
fn ozet_cikar(&self) -> String {
format!("{}: {}", self.kullanici_adi, self.icerik)
}
}
fn main() {
let tweet = Tweet {
kullanici_adi: String::from("rust_dev"),
icerik: String::from("Rust Trait sistemi muazzam! 🦀"),
yanit_mi: false,
retweet_mi: false,
};
println!("Yeni tweet: {}", tweet.ozet_cikar());
}
---
💡 3. Varsayılan Metot İmplementasyonu (Default Implementation) ⚙️
Trait içinde metodun sadece imzasını değil, varsayılan bir gövde (default body) de yazabilirsiniz. Eğer uygulayan Struct bu metodu ezmezse (override), varsayılan kod çalışır.
pub trait Ozetlenebilir {
fn ozet_cikar(&self) -> String {
String::from("(Devamını oku...)") // Varsayılan davranış
}
}
// Eğer Struct içinde 'impl Ozetlenebilir for Haber {}' yazıp içi boş bırakılırsa,
// varsayılan 'ozet_cikar' metodu geçerli olur!
---
🎯 4. Parametre Olarak Trait Kullanımı: `impl Trait` 🎯
Bir fonksiyona parametre olarak "Belirli bir Trait'i uygulayan herhangi bir tip" geçirebiliriz.
pub fn ozeti_yazdir(oge: &impl Ozetlenebilir) {
println!("Haber Özeti: {}", oge.ozet_cikar());
}
Bu fonksiyon; `Haber`, `Tweet` veya `Ozetlenebilir` Trait'ine sahip başka herhangi bir Struct örneğini parametre olarak alabilir!
---
🚧 5. Trait Bounds (Trait Kısıtlamaları) ve `where` Cümlesi ⛓️
`impl Trait` syntax'ı aslında **Trait Bound** yapısının kısa yazımıdır. Karmaşık durumlarda Trait Bound ve `where` kelimesi okunabilirliği ciddi oranda artırır.
### Uzun Trait Bound Yazımı:
pub fn bildirim_gonder<T: Ozetlenebilir>(item1: &T, item2: &T) {
println!("Bildirim: {}", item1.ozet_cikar());
}
### Birden Fazla Trait Şartı (`+` Operatörü):
`T` tipinin hem `Ozetlenebilir` hem de `Display` Trait'ini uygulamasını isteyebiliriz:
pub fn detayli_yazdir<T: Ozetlenebilir + std::fmt:
### `where` Cümlesi İle Temiz Kod:
Birden fazla jenerik parametre ve kısıtlama olduğunda imza kirlenir. `where` bunu çözer:
// Okunması zor yazım:
fn fonksiyon<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 { ... }
// 'where' ile temiz yazım:
fn fonksiyon<T, U>(t: &T, u: &U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{
// Fonksiyon gövdesi
}
---
↩️ 6. Dönüş Tipi Olarak Trait: `returns impl Trait` 🔄
Bir fonksiyonun belirli bir Trait'i uygulayan anonim bir tip döndürmesini sağlayabiliriz:
fn rastgele_yazar_olustur() -> impl Ozetlenebilir {
Tweet {
kullanici_adi: String::from("anonim"),
icerik: String::from("Kod yazmaya devam!"),
yanit_mi: false,
retweet_mi: false,
}
}
⚠️ **Kısıtlama:** `impl Trait` dönüş tipinde, fonksiyon gövdesinden YALNIZCA TEK BİR somut tip dönebilir. Koşula göre (`if/else`) hem `Tweet` hem `Haber` döndüremezsiniz! (İleride `Box<dyn Trait>` ile bu kısıtlamayı aşmayı göreceğiz).
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Trait kavramını, `impl Trait for Struct` yapısını, varsayılan metotları, Trait Bound kısıtlamalarını ve `where` cümlesini inceledik.
👉 **Bölüm 13'te Bizi Ne Bekliyor?**
• Rust'ın Referans Güvenliği: **Lifetimes (Yaşam Süreleri)** ⏳
• Borrow Checker mekanizması ve Dangling Pointer önleme
• Lifetime Annotations
(`'a`, `'static`)
• Struct ve Fonksiyonlarda Lifetime kullanımı
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! 🦀✨
🔒 Bu içeriği görmek için giriş yapın