Soru tarihçesi
Rust, yöntemler kavramını nesne yönelimli dillerden ödünç alır, ancak bunları farklı bir şekilde gerçekleştirir: alışılmış olan this veya self yerine yöntemler açıkça bir self parametresi alır. İlişkili işlevler ise diğer dillerdeki statik yöntemlerin bir alternatifi olarak ortaya çıkmıştır — bunlar tip ile ilişkilidir, ancak belirli bir değere bağlı değildir.
Sorun
Sıklıkla yöntemler, ilişkili işlevler ve serbest işlevler karıştırılır. self içeren bir yöntemi ne zaman kullanmalı, self içermeyen bir ilişkili işlevi ne zaman kullanmalıyız? Görünürlük, otomatik dereferans, sahiplik aktarımı gibi sorunlar vardır.
Çözüm
Rust'taki yöntemler, impl bloğu içinde ilk parametre olarak self/ &self/ &mut self ile tanımlanır (genellikle struct veya enum için). Bir örnek üzerinde çağrılır: object.method(). İlişkili işlevler (örneğin, new, from) de impl içinde tanımlanır, ancak ilk parametre olarak self olmadan ve çift iki nokta ile çağrılır: Type::function().
Kod örneği:
struct Point { x: f64, y: f64, } impl Point { // İlişkili işlev (constructor) fn new(x: f64, y: f64) -> Self { Self { x, y } } // Yöntem: self'i gerektirir fn distance_from_origin(&self) -> f64 { (self.x.powi(2) + self.y.powi(2)).sqrt() } } let p = Point::new(3.0, 4.0); printf!("{}", p.distance_from_origin()); // 5.0
Ana özellikler:
:: ile çağrılabilirİlişkili işlevleri bir örnek üzerinden (nokta ile) çağırmak mümkün mü?
Bu olasıdır (örneğin, p.new(1.0, 2.0)), ancak son derece önerilmez: bu yanıltıcıdır çünkü ilişkili işlev mevcut nesneye erişime sahip değildir ve örnek göz ardı edilerek geçilir. Daha iyi bir kullanım Type::func() sentaksını kullanmaktır.
Kod örneği:
let p = Point::new(1.0, 2.0); let q = p.new(0.0, 0.0); // Çalışır, ama en iyi uygulama değil!
Yöntemler asenkron olabilir mi?
Evet. Yöntemler, serbest işlevler gibi async anahtar kelimesi ile tanımlanabilir:
impl Foo { async fn do_async(&self) { // ... } }
Bir impl bloğu içinde hem yöntemler hem de ilişkili işlevler tanımlamak mümkün mü?
Evet — her türlü kombinasyon mümkündür. Ayrıca, bir tip için birden fazla impl bloğu tanımlamak da mümkündür.
Yeni başlayan birisi, new işlevini impl dışında tanımladı ve onu bir constructor olarak kullanmaya çalıştı; ardından yanlışlıkla bir örnek üzerinden çağırdı: p.new(1.0, 2.0).
Artılar:
Hızlı çalışır (derleyici buna izin verir).
Eksiler:
Kod okunaksız, bakım zor, self ile doğru yöntemler kullanmak zordur.
Tüm yöntemler ve ilişkili işlevler, yalnızca impl içinde tanımlanmış olup, çağrı için doğru sözdizimleri kullanılmıştır (Type::new() constructorlar için, obj.method() eylemler için).
Artılar:
Yüksek okunabilirlik, en iyi uygulamalara uygunluk.
Eksiler:
Rust'ın deyimlerini bilme ve sözdizimine dikkat etme gerektirir.