Skip to content

Commit 26208c0

Browse files
committed
Updated readme document
1 parent 74da685 commit 26208c0

1 file changed

Lines changed: 276 additions & 2 deletions

File tree

Lesson_08/README.md

Lines changed: 276 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
**trait** türü belirli bir davranış kümesini tanımlayan ve bunu bir veya birden fazla veri yapısına uygulayabilen bir
44
enstrüman olarak düşünülebilir. C# tarafındaki **interface** türüne ve kullanım amacına benzer olduğunu söyleyebiliriz.
55
Özellikle **generic** yapılarla kullanıldığında büyük esneklik sağlar _(ki Generics bölümünde trait'lerin dinamik
6-
kullanımına değinilmektedir)_ Rust standart kütüphanesi ile gelen bir çok faydalı ve kullanışlı trait de vardır. **Debug
7-
**, **Copy**, **Clone**, **Add**, **Display**, **From** ve benzerleri bunlara örnek olarak gösterilebilir.
6+
kullanımına değinilmektedir)_ Rust standart kütüphanesi ile gelen bir çok faydalı ve kullanışlı trait de vardır.
7+
**Debug**, **Copy**, **Clone**, **Add**, **Display**, **From** ve benzerleri bunlara örnek olarak gösterilebilir.
88

99
## Trait Tanımlama ve Kullanımı
1010

@@ -202,6 +202,280 @@ fn main() {
202202
}
203203
```
204204

205+
## Rust'ta Yaygın Kullanılan Trait'ler ve Kullanım Örnekleri
206+
207+
Rust programlama dili, güçlü tür sistemine sahip olmasıyla da bilinir. Bu sistemin önemli bir parçası da **trait**
208+
yapılarıdır. Trait'ler, bir türün belirli bir davranışı nasıl uygulayacağını belirten arayüzlerdir. Rust standart
209+
kütüphanesi birçok yerleşik trait sunar. Var olan trait'lerin bir kısmı **derive** direktifi ile implemente edilirken
210+
bazıları da açıkça yazılır ve tanımladıkları fonksiyonlar ezilir. Aşağıdaki bölümlerde sık kullanılan trait örneklerine
211+
yer verilmiştir.
212+
213+
### Debug
214+
215+
Rust'ta bir yapıyı **Debug** trait'ini uygulamadan **println!** makrosu ile **{:#?}** veya **{:?}** formatında yazdırmak
216+
mümkün değildir. **Debug** trait'ini etkinleştirmek için **#[derive(Debug)]** özelliği kullanılmalıdır.
217+
218+
```rust
219+
#[derive(Debug)]
220+
struct Player {
221+
name: String,
222+
level: u8,
223+
last_score: f32,
224+
}
225+
```
226+
227+
### Display
228+
229+
**Display** trait, bir yapının _(struct)_ veri içeriğinin istenilen şekilde yazdırılmasını/okunmasını sağlar. Bu trait'i
230+
uygulamak için **std::fmt::Display** trait'inin **fmt** metodu override edilmelidir. Aşağıdaki örnekte **Player** veri
231+
yapısının örneğin bir println makrosunda kullanılması halinde ekrana ne yazılacağı programlanmıştır. Bu yaklaşım sadece
232+
println ile değil nesnenin String ifadelerinde de kullanılabilir. Örneğin bir CSV içeriğini hazırlarken de ele
233+
alınabilir, log bilgisi olarak bir kaynağa gönderilirken de.
234+
235+
```rust
236+
use std::fmt::{Display, Formatter};
237+
238+
impl Display for Player {
239+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
240+
write!(
241+
f,
242+
"{}({}) last score is {}",
243+
self.name, self.level, self.last_score
244+
)
245+
}
246+
}
247+
248+
fn main() {
249+
let max_payne = Player {
250+
name: String::from("Max Payne"),
251+
level: 80,
252+
last_score: 167.58,
253+
};
254+
// Debug trait'ini uygulamazsak
255+
// `Player` does not implement `Debug` (required by `{:#?}`): E0277
256+
println!("{:#?}", max_payne);
257+
258+
// Aşağıdaki kullanım ise Display trait'ini uygulamayı gerektirir
259+
println!("{}", max_payne);
260+
}
261+
```
262+
263+
### Clone ve Copy
264+
265+
Rust'ta veri sahipliği _(ownership)_ önemli bir konudur. **Clone** trait'i, bir nesnenin kopyasını oluşturmayı sağlar.
266+
**Copy** trait'i ise küçük ve taşınabilir türler için tercih edilir. **Shallow Copy** durumlarında **Copy** trait ön
267+
plana çıkarken, **Deep Copy** operasyonlarında **Clone** trait ele alınabilir. **Velocity** isimli struct'ı ve bu türü
268+
parametre olarak kullanan **accelarate** fonksiyonunu göz önüna alalım. Velocity veri yapısı Debug, PartialEq, Copy ve
269+
Clone trait'lerini implemente etmektedir.
270+
271+
```rust
272+
#[derive(Debug, PartialEq, Copy, Clone)]
273+
struct Velocity {
274+
x: f32,
275+
y: f32,
276+
}
277+
278+
fn accelerate(mut speed: Velocity) {
279+
speed.x += 1.0;
280+
speed.y += 1.0;
281+
println!("Accelerating: {:#?}", speed);
282+
}
283+
284+
fn main() {
285+
let max_payne = Player {
286+
name: String::from("Max Payne"),
287+
level: 80,
288+
last_score: 167.58,
289+
};
290+
291+
// Clone trait uygulaması
292+
let mut red_one = max_payne.clone();
293+
red_one.name = String::from("Red Leader One");
294+
println!("{:#?}", red_one);
295+
296+
// PartialEq ve Copy, Clone örnekleri
297+
let my_speed = Velocity { x: 10.0, y: 0.0 };
298+
let your_speed = Velocity { x: 10.0, y: 0.0 };
299+
if my_speed == your_speed {
300+
println!("{my_speed:?} is equal to {your_speed:?}")
301+
}
302+
accelerate(your_speed);
303+
// Eğer Velocity için Copy trait kullanmazsak
304+
// Value used after being moved [E0382] derleme hatası oluşur
305+
if my_speed == your_speed {
306+
println!("{my_speed:?} is equal to {your_speed:?}")
307+
} else {
308+
println!("{my_speed:?} is not equal to {your_speed:?}")
309+
}
310+
}
311+
```
312+
313+
Bir önceki örnekte **PartialEq** trait'i derive direktifi ile implemente edilmiştir. Bu durumda rust
314+
varsayılan trait davranışını Velocity için uygular ve içerdiği tüm primitive tipler karşılaştırmaya dahil edilir. Ancak
315+
bazı durumlarda sadece belli alanlar üzerinden karşılaştırma yapılmak istenebilir. LogStamp isimli aşağıdaki yapıyı ele
316+
alalım. Sadece id değerleri üzerinden iki değişkenin eşit olup olmadığı kontrol edilmek isteniyorsa **PartialEq**
317+
trait'i LogStamp türü için implemente edilebilir.
318+
319+
```rust
320+
#[derive(Debug)]
321+
struct LogStamp {
322+
id: i32,
323+
time: String,
324+
content: String,
325+
}
326+
327+
impl PartialEq for LogStamp {
328+
fn eq(&self, other: &Self) -> bool {
329+
self.id == other.id
330+
}
331+
}
332+
333+
fn main() {
334+
let log_1 = LogStamp {
335+
id: 1234,
336+
time: String::from("2024-10-20T09:56-PM"),
337+
content: String::from("Check with ping"),
338+
};
339+
let log_2 = LogStamp {
340+
id: 1234,
341+
time: String::from("2024-10-20T09:58-PM"),
342+
content: String::from("Check with ping"),
343+
};
344+
if log_1 == log_2 {
345+
println!("Same logs\n{log_1:?}\n{log_2:?}");
346+
}
347+
}
348+
```
349+
350+
### Default
351+
352+
**Default** trait, bir struct türünün varsayılan değerlerle oluşturulmasında kullanılır. Aşağıdaki örnekte yer alan Game
353+
yapısı Default trait ile oluşturulurken içeriğine bazı ilk değerler verilmektedir. **Display** trait eğer derive
354+
direktifi ile kullanılırsa türün içeriğindeki alanlar içinde varsayılan değerler set edilir ancak aşağıdaki örnekte
355+
olduğu gibi içeriğin özel verilerle oluşturulması da sağlanabilir.
356+
357+
### Örnek:
358+
359+
```rust
360+
#[derive(Debug)]
361+
struct Game {
362+
fps: u8,
363+
title: String,
364+
screen_width: u32,
365+
screen_height: u32,
366+
}
367+
368+
impl Default for Game {
369+
fn default() -> Self {
370+
Game {
371+
fps: 30,
372+
title: String::from("A Simple Game"),
373+
screen_width: 1280,
374+
screen_height: 960,
375+
}
376+
}
377+
}
378+
379+
fn main() {
380+
let my_game = Game::default();
381+
println!("{:#?}", my_game);
382+
println!("{}", my_game);
383+
}
384+
```
385+
386+
### FromStr
387+
388+
**FromStr** trait, metinsel bir ifadenin belirli bir veri türüne dönüştürülmesinde kullanılır. Aşağıdaki örnekte
389+
**SystemColor** isimli veri yapısının aralarında **:** işaret bulunan bir RGB(Red Green Blue) formatından üretilmesi ele
390+
alınmaktadır. Pek tabii dönüştürme operasyonunun başarısız olması ihtimali **Result** türü ile kontrol altında
391+
tutulmaktadır.
392+
393+
```rust
394+
use std::str::FromStr;
395+
use std::num::ParseIntError;
396+
397+
#[derive(Debug, Copy, Clone)]
398+
struct SystemColor {
399+
r: u8,
400+
g: u8,
401+
b: u8,
402+
}
403+
404+
#[derive(Debug)]
405+
enum ColorParseError {
406+
WrongArgumentCount,
407+
ParseError(ParseIntError),
408+
}
409+
410+
impl FromStr for SystemColor {
411+
type Err = ColorParseError;
412+
413+
fn from_str(s: &str) -> Result<Self, Self::Err> {
414+
let parts: Vec<&str> = s.split(':').collect();
415+
if parts.len() != 3 {
416+
return Err(ColorParseError::WrongArgumentCount);
417+
}
418+
419+
let r = parts[0].parse::<u8>().map_err(ColorParseError::ParseError)?;
420+
let g = parts[1].parse::<u8>().map_err(ColorParseError::ParseError)?;
421+
let b = parts[2].parse::<u8>().map_err(ColorParseError::ParseError)?;
422+
423+
Ok(SystemColor { r, g, b })
424+
}
425+
}
426+
427+
fn main() {
428+
let valid_color = "125:100:100".parse::<SystemColor>();
429+
match valid_color {
430+
Ok(color) => println!("Parsed color: {:?}", color),
431+
Err(e) => println!("Error parsing color: {:?}", e),
432+
}
433+
434+
let invalid_color = "red:100:100".parse::<SystemColor>();
435+
match invalid_color {
436+
Ok(color) => println!("Parsed color: {:?}", color),
437+
Err(e) => println!("Error parsing color: {:?}", e),
438+
}
439+
}
440+
```
441+
442+
### Drop
443+
444+
**Drop** trait, bir nesne bellekten kaldırılırken belirli işlemlerin gerçekleştirilmesi istendiği durumlar için
445+
idealdir. Harici kaynaklar kullanan bir nesnenin kullandığı kaynaklarla ilgili işlemler yapmak buna örnek
446+
gösterilebilir.
447+
448+
```rust
449+
#[derive(Debug)]
450+
struct Service {
451+
title: String,
452+
address: String,
453+
}
454+
455+
impl Service {
456+
fn call(&self) {
457+
println!("Service call");
458+
}
459+
}
460+
461+
impl Drop for Service {
462+
fn drop(&mut self) {
463+
println!("Closing temp connections and releasing resources.");
464+
}
465+
}
466+
467+
fn main() {
468+
{
469+
let author_service = Service {
470+
title: String::from("Author service"),
471+
address: String::from("https://azon/services/author"),
472+
};
473+
println!("{:#?} is ready.", author_service);
474+
author_service.call();
475+
} // Scope sonu, drop trait tetiklenir
476+
}
477+
```
478+
205479
## Özet
206480

207481
| Konu | Açıklama |

0 commit comments

Comments
 (0)