Çoklu Sınırlandırıcılar
Coddy'nin Rust Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 41 / 61.
Bazen tek bir trait bound (özellik sınırı) yeterli olmaz. Hem yazdırılabilen hem de bir özet sunabilen genel bir türe ihtiyaç duyabilirsiniz. Rust, + sözdizimini kullanarak birden fazla trait gereksinimi belirlemenize olanak tanır.
Bir türün iki trait'i birden uygulaması gerektiğini şu şekilde belirtebilirsiniz:
use std::fmt::Display;
trait Summary {
fn summarize(&self) -> String;
}
fn announce<T: Display + Summary>(item: T) {
println!("Breaking news: {}", item);
println!("Summary: {}", item.summarize());
}
T: Display + Summary sınırı, "T'nin hem Display hem de Summary trait'lerini uygulaması gerektiği" anlamına gelir. Fonksiyonun içinde, her iki trait'in de yeteneklerini kullanabilirsiniz; {} ile yazdırma (Display trait'inden) ve summarize() metodunu çağırma (Summary trait'inden).
İhtiyaç duyduğunuz kadar trait'i birbirine bağlayabilirsiniz:
fn process<T: Display + Summary + Clone>(item: T) {
// Yazdırabilir, özetleyebilir VE kopyalayabilir
}
Bu desen, fonksiyonunuz birden fazla davranışa dayandığında esastır. Herhangi bir türü kabul edip çalışmasını ummak yerine, tam olarak hangi yeteneklerin gerekli olduğunu açıkça belirtirsiniz ve derleyici bunu derleme zamanında zorunlu kılar.
Görev
KolayÖğelerin birden fazla yeteneğe sahip olmasını gerektiren bir ürün denetim sistemi kuralım! Birden fazla sınırı birleştirmek için + sözdiziminin nasıl kullanıldığını gösteren, hem özel bir trait'i hem de standart bir trait'i uygulayan türleri kabul eden genel (generic) bir fonksiyon oluşturacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
product.rs:&selfalan ve denetim ayrıntılarını içeren birStringdöndüreninspectadlı bir yönteme sahip genel birInspectabletrait'i tanımlayın. Ardından, genelname(String) veserial(u32) alanlarına sahip genel birGadgetyapısı (struct) oluşturun. Gadget'ınız hemInspectable("Inspecting: {}"formatında döndüren) hem destd::fmt::Display("{} (SN: {})"şeklinde formatlayan) trait'lerini uygulamalıdır. Son olarak, hemDisplayhem deInspectabletrait'lerini uygulayan herhangi birTtürünü kabul edenfull_reportadında genel bir fonksiyon oluşturun. Bu fonksiyon iki satır yazdırmalıdır: önce{}formatlayıcısını kullanarak öğeyi, ardındaninspect()çağırmanın sonucunu.main.rs: Ürün modülünüzü dahil edin ve sağlanan girdileri kullanarak birGadgetörneği oluşturun. Gadget'ınızın her iki trait gereksinimini de karşıladığını göstermek için gadget'ınızlafull_reportfonksiyonunu çağırın.
Birden fazla sınırın (multiple bounds) gücü, full_report fonksiyonunuzun her iki trait'in yeteneklerini de kullanabilmesidir; öğeyi güzel bir şekilde görüntülemek VE denetim ayrıntılarını almak; bunların tümü derleme zamanında garanti edilir.
Çıktınız hem görüntüleme formatını hem de denetim sonucunu göstermelidir:
{name} (SN: {serial})
Inspecting: {name}Örneğin, Smartwatch ve 98765 girdileriyle:
Smartwatch (SN: 98765)
Inspecting: Smartwatchİki girdi alacaksınız: gadget adı ve seri numarası (u32 olarak ayrıştırın).
Kopya kağıdı
+ söz dizimini kullanarak genel (generic) bir tür üzerinde birden fazla trait sınırı (trait bound) belirtebilirsiniz:
fn function_name<T: Trait1 + Trait2>(item: T) {
// Her iki trait'in yeteneklerini kullanabilir
}
Display ve özel bir trait ile örnek:
use std::fmt::Display;
trait Summary {
fn summarize(&self) -> String;
}
fn announce<T: Display + Summary>(item: T) {
println!("Breaking news: {}", item);
println!("Summary: {}", item.summarize());
}
İhtiyaca göre birden fazla trait'i zincirleyebilirsiniz:
fn process<T: Display + Summary + Clone>(item: T) {
// Yazdırabilir, özetleyebilir VE kopyalayabilir (clone)
}
Derleyici, türün belirtilen tüm trait'leri uyguladığını derleme zamanında zorunlu kılar.
Kendin dene
mod product;
use product::{Gadget, full_report};
fn main() {
// Girdileri oku
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut serial_input = String::new();
std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
// YAPILACAK: İsim ve seri numarası ile bir Gadget örneği oluşturun
// YAPILACAK: Gadget'ınızla full_report'u çağırın
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1Metotlar ve Davranış
Uygulama Bloklarına GirişSelf ParametresiDeğiştirilebilir Metotlarİlişkili FonksiyonlarBirden Fazla Uygulama BloğuMetot ZincirlemeÖzet - Dikdörtgen Eylemleri4Proje: Sanal Evcil Hayvan
Evcil Hayvanı TanımlamaEvcil Hayvanı Besleme2Kapsülleme ve Modüller
Modül TemelleriPublic Anahtar KelimesiPrivate AlanlarGetter'larSetter'larÖzet - Güvenli Kasa5Generic Yapılar
Generic Struct'larGeneric MetotlarÇoklu Generic TürlerGeneric FonksiyonlarÖzet - Koordinat Noktası8Sınırlandırıcı Olarak Trait'ler
Trait Sınırlandırıcı SözdizimiÇoklu SınırlandırıcılarWhere CümleciğiTrait'ler ile Tip DöndürmeÖzet - Generic Yazıcı11Rust'ta Tasarım Kalıpları
Newtype KalıbıKompozisyonDrop Trait'iFrom ve IntoÖzet - Smart Pointer Mock3İleri Seviye Enum'lar
Veri İçeren Enum'larEnum MetotlarıVeri Varyantlarını EşlemeOption Enum'ına Yeniden BakışÖzet - Shape Enum6Trait Tanımlama
Trait Nedir?Traitleri UygulamaVarsayılan UygulamalarVarsayılanları Geçersiz KılmaParametreli TraitlerÖzet - Media Player