Skip to content

Commit 74da685

Browse files
committed
Added document about traits
1 parent cd5852c commit 74da685

5 files changed

Lines changed: 229 additions & 6 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[workspace]
2-
members = ["Lesson_00", "Lesson_01", "Lesson_02", "Lesson_03", "Lesson_04", "Lesson_05", "Lesson_06", "Lesson_07", "collector", "drone-lab", "sysco", "sysco2"]
2+
members = ["Lesson_00", "Lesson_01", "Lesson_02", "Lesson_03", "Lesson_04", "Lesson_05", "Lesson_06", "Lesson_07", "Lesson_08", "collector", "drone-lab", "sysco", "sysco2"]
33

44
resolver = "2"

Lesson_08/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "Lesson_08"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]

Lesson_08/README.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Ders 08: Trait Kullanımı
2+
3+
**trait** türü belirli bir davranış kümesini tanımlayan ve bunu bir veya birden fazla veri yapısına uygulayabilen bir
4+
enstrüman olarak düşünülebilir. C# tarafındaki **interface** türüne ve kullanım amacına benzer olduğunu söyleyebiliriz.
5+
Ö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.
8+
9+
## Trait Tanımlama ve Kullanımı
10+
11+
Aşağıdaki örnekte **Service** adında bir trait tanımlanmıştır. **activate**, **deactivate** ve **status** olmak üzere üç
12+
metot bildirimi/davranış tanımı içermektedir.
13+
14+
```rust
15+
trait Service {
16+
fn activate(&mut self);
17+
fn deactivate(&mut self);
18+
fn status(&self) {
19+
println!("Service status");
20+
}
21+
}
22+
```
23+
24+
Bu trait aşağıdaki gibi Redis ve HeathCheck isimli veri yapılarına uygulanabilir.
25+
26+
```rust
27+
struct Redis;
28+
struct HealthCheck {
29+
is_online: bool,
30+
}
31+
32+
impl Service for Redis {
33+
fn activate(&mut self) {
34+
println!("Activating Redis");
35+
}
36+
fn deactivate(&mut self) {
37+
println!("Deactivating Redis");
38+
}
39+
}
40+
41+
impl Service for HealthCheck {
42+
fn activate(&mut self) {
43+
self.is_online = true;
44+
println!("Activating HealthCheck");
45+
}
46+
fn deactivate(&mut self) {
47+
println!("Deactivating HealthCheck");
48+
}
49+
fn status(&self) {
50+
println!("Service status: {}", self.is_online);
51+
}
52+
}
53+
```
54+
55+
Dikkat edilmesi gereken noktalardan birisi Redis veri yapısında status isimli davranışın yazılmamasıdır. Dolayısıyla
56+
default trait davranışının uygulandığını ifade edebiliriz.
57+
58+
## Fonksiyon Parametresi Olarak Trait Kullanımı
59+
60+
Bir trait'i parametre olarak alan fonksiyonlar da yazılabilir ve böylece söz konusu trait'i uygulayan herhangi bir yapı
61+
ilgili fonksiyonda kullanılabilir. Trait'leri fonksiyonlara almanın iki farklı yolu vardır.
62+
63+
- **impl Trait Kullanımı**
64+
65+
```rust
66+
fn start_sample(service: &mut impl Service) {
67+
service.activate();
68+
println!("{:?}", service.status());
69+
service.deactivate();
70+
println!("{:?}", service.status());
71+
}
72+
```
73+
74+
- **Generic Trait Kullanımı**
75+
76+
```rust
77+
fn start_sample2<T: Service>(service: &mut T) {
78+
service.activate();
79+
println!("{:?}", service.status());
80+
service.deactivate();
81+
println!("{:?}", service.status());
82+
}
83+
```
84+
85+
Buraya kadar anlatılan örnekler aşağıdaki kod parçasındaki gibi denenebilirs.
86+
87+
```rust
88+
fn main() {
89+
let mut redis_instance = Redis;
90+
let mut doctor = HealthCheck { is_online: false };
91+
92+
start_sample(&mut redis_instance);
93+
start_sample(&mut doctor);
94+
start_sample2(&mut redis_instance);
95+
}
96+
```
97+
98+
## Varsayılan Trait Metodu
99+
100+
Bazı durumlarda bir trait içinde **varsayılan** işlevsellik sunan bir davranış tanımlanabilir. Bu metot, trait'i
101+
uygulayan yapı tarafından **ezilmek/override zorunda değildir**. Aşağıdaki kod parçasını göz önüne alalım. Örnekte *
102+
*Payment** isimli bir trait tanımlanmıştır. **pay** metodu varsayılan olarak nakit ödeme işlemini icra eder ama
103+
istenirse farklı bir veri yapısında bu davranış farklı şekilde uygulanabilir.
104+
105+
```rust
106+
trait Payment {
107+
fn pay(&self, amount: f64) {
108+
println!("Paid {:.2} with cash.", amount);
109+
}
110+
}
111+
```
112+
113+
Farklı ödeme türleri için söz konusu trait'in aşağıdaki kod parçasında olduğu gibi uygulandığını düşünelim. Dikkat
114+
edileceği üzere kredi kartı ödemeleri için aynı davranışın farklı bir işleyişi tasarlanmıştır.
115+
116+
```rust
117+
struct DebitCard;
118+
impl Payment for DebitCard {}
119+
120+
struct CompanyAccount;
121+
impl Payment for CompanyAccount {}
122+
123+
struct CreditCard;
124+
impl Payment for CreditCard {
125+
fn pay(&self, amount: f64) {
126+
let amount_with_commision = amount * 1.1;
127+
println!("Paid {:.2} with credit card.", amount_with_commision);
128+
}
129+
}
130+
131+
fn main() {
132+
let debit_payment = DebitCard;
133+
let company_payment = CompanyAccount;
134+
let card_payment = CreditCard;
135+
136+
debit_payment.pay(100.0);
137+
card_payment.pay(100.0);
138+
company_payment.pay(100.0);
139+
}
140+
```
141+
142+
## Trait Object
143+
144+
Bazı durumlarda trait'i implemente eden nesneleri **dinamik olarak** saklamak isteyebiliriz. Bu gibi durumlarda **Trait
145+
Object** kullanılır. Çizim davranışını tarifleyen **Draw** isimli bir trait nesnesini ele alalım.
146+
147+
```rust
148+
trait Draw {
149+
fn draw(&self);
150+
}
151+
```
152+
153+
ve bu trait'i implemente eden bazı veri yapıları oluşturalım.
154+
155+
```rust
156+
struct Circle;
157+
struct Square;
158+
struct Player;
159+
160+
impl Draw for Circle {
161+
fn draw(&self) {
162+
println!("Drawing a circle");
163+
}
164+
}
165+
166+
impl Draw for Square {
167+
fn draw(&self) {
168+
println!("Drawing a square");
169+
}
170+
}
171+
172+
impl Draw for Player {
173+
fn draw(&self) {
174+
println!("Drawing a player");
175+
}
176+
}
177+
```
178+
179+
Bir vektör değişkeninde **Draw trait**' ini uygulayan **farklı nesneleri** tutabilir ve toplu işlemler
180+
gerçekleştirebiliriz. Özellikle aynı davranışı farklı şekillerde uygulayan ama sayıları çalışma zamanında belli olan
181+
heap odaklı nesne toplulukları göz önüne alındığında bu teknik oldukça kullanışlıdır.
182+
183+
```rust
184+
fn draw_shapes(shapes: &Vec<&dyn Draw>) {
185+
for shape in shapes.iter() {
186+
shape.draw();
187+
}
188+
}
189+
```
190+
191+
Örnek bir kullanım,
192+
193+
```rust
194+
fn main() {
195+
// Trait Object kullanımı
196+
let red_ball = Circle;
197+
let blue_ball = Circle;
198+
let wall = Square;
199+
let warrior = Player;
200+
let level_1: Vec<&dyn Draw> = vec![&red_ball, &blue_ball, &wall, &warrior];
201+
draw_shapes(&level_1);
202+
}
203+
```
204+
205+
## Özet
206+
207+
| Konu | Açıklama |
208+
|-----------------------------|----------------------------------------------------------------|
209+
| **Trait Tanımlama** | `trait TraitAdı { ... }` şeklinde tanımlanır. |
210+
| **Trait Implementasyonu** | `impl TraitAdı for StructAdı { ... }` |
211+
| **Generic Trait Kullanımı** | `fn func<T: TraitAdı>(param: &T) { ... }` |
212+
| **Trait Object Kullanımı** | `&dyn TraitAdı` şeklinde dinamik nesne tutulur. |
213+
| **Varsayılan Trait Metodu** | Trait içinde metod için varsayılan implementasyon yazılabilir. |

Lesson_08/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("Hello, world!");
3+
}

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ yer aldığı repodur.
1313
- [Ders 05 - Enum Veri Türü, Pattern Matching](./Lesson_05/README.md)
1414
- [Ders 06 - Lifetime(Yaşam Ömrü) Kavramı](./Lesson_06/README.md)
1515
- [Ders 07 - Generic Türler](./Lesson_07/README.md)
16-
- [Ders 08 - Closures]()
17-
- [Ders 09 - Smart Pointers]()
18-
- [Ders 10 - Threads]()
19-
- [Ders 11 - Channels]()
20-
- [Ders 12 - Macros]()
16+
- [Ders 08 - Traits](./Lesson_08/README.md)
17+
- [Ders 09 - Closures]()
18+
- [Ders 10 - Smart Pointers]()
19+
- [Ders 11 - Threads]()
20+
- [Ders 12 - Channels]()
21+
- [Ders 13 - Macros]()
2122
- [Destekleyici Bölümler]()
2223
- [Birim Test](UnitTests.md)
2324
- [Hata Yönetimi](ErrorHandling.md)

0 commit comments

Comments
 (0)