Skip to content

Commit b6536b3

Browse files
author
murat.genc
committed
02.5 object-oriented
1 parent 521cbbd commit b6536b3

File tree

2 files changed

+322
-1
lines changed

2 files changed

+322
-1
lines changed

Diff for: tr/02.4.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,4 @@ func main() {
211211

212212
- [Rehber](preface.md)
213213
- Önceki bölüm: [Kontrol ifadeleri ve fonksiyonlar](02.3.md)
214-
- Sonraki bölüm: [Object-oriented](02.5.md)
214+
- Sonraki bölüm: [Nesne-Yönelim](02.5.md)

Diff for: tr/02.5.md

+321
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
# Nesne-Yönelim
2+
3+
Son iki bölüm de fonksiyonlar ve `struct` hakkında konuştuk, ancak fonksiyonları `struct` ın bir alanı olarak kullanmayı düşündünüz mü? Bu bölümde, alıcısı olan `method` olarak adlandırılan başka bir fonksiyon biçimi tanıtacağım.
4+
5+
## method
6+
7+
Bir "Dikdortgen" struct tanımladığınızı ve onun alanını hesaplamak istediğinizi varsayalım. Bu amaca ulaşmak için genellikle aşağıdaki kodu kullanırdık.
8+
```Go
9+
package main
10+
11+
import "fmt"
12+
13+
type Dikdortgen struct {
14+
genislik, yukseklik float64
15+
}
16+
17+
func alan(r Dikdortgen) float64 {
18+
return r.genislik * r.yukseklik
19+
}
20+
21+
func main() {
22+
d1 := Dikdortgen{12, 2}
23+
d2 := Dikdortgen{9, 4}
24+
fmt.Println("d1 in alanı: ", alan(d1))
25+
fmt.Println("d2 nin alanı: ", alan(d2))
26+
}
27+
28+
```
29+
Yukarıdaki örnek bir Dikdortgen'in alanını hesaplayabilir. Burada `alan` isimli fonksiyonu kullanıyoruz, fakat bu fonksiyon Dikdortgen struct'ının bir method u değil(klasik nesne yönelimli dillerdeki sınıf nethodları gibi). Fark edebileceğiniz gibi fonksiyon ve struct iki bağımsız şeydir.
30+
31+
Şimdiye kadar sorun değil. Bununla birlikte, bir dairenin, karenin, beşgenin veya başka herhangi bir şeklin alanını da hesaplamanız gerekiyorsa, çok benzer adlara sahip ek fonksiyonlar eklemeniz gerekecektir.
32+
33+
![](images/2.5.rect_func_without_receiver.png?raw=true)
34+
35+
Figure 2.8 Fonksiyon ve struct arasındaki ilişki
36+
37+
Açıkçası bu hiç hoş değil. Ayrıca, alan fonksiyonu bir dairenin veya dikdörtgenin özelliği olmalıdır.
38+
39+
İşte `method` un devreye gireceği nokta burasıdır. `method`, bir türe/tipe bağlı fonksiyondur. `func` anahtar sözcüğünün, bu methodun ana gövdesi olan `receiver` adlı bit parametreye sahip olması haricinde, fonksiyonlar benzer bir sözdizimi vardır.
40+
41+
Aynı örneği kullanarak, `Dikdortgen.Alan()` çevresel bir fonksiyon yerine doğrudan Dikdortgen'e aittir. Daha spesifik olarak, `yukseklik`, `genislik` ve `Alan()` hepsi Dikdortgen'e aittir.
42+
43+
Rob Pike'ın dediği gibi.
44+
45+
"Bir method, alıcı olarak adlandırılan ilk örtülü argüman olan bir fonksiyondur."
46+
47+
method sözdimi.
48+
```Go
49+
func (r ReceiverType) funcName(parameters) (results)
50+
```
51+
Örneğimizi `method` kullanarak değiştirelim.
52+
```Go
53+
package main
54+
55+
import (
56+
"fmt"
57+
"math"
58+
)
59+
60+
type Daire struct {
61+
yaricap float64
62+
}
63+
64+
type Dikdortgen struct {
65+
genislik, yukseklik float64
66+
}
67+
68+
// method
69+
func (daire Daire) Alan() float64 {
70+
return daire.yaricap * daire.yaricap * math.Pi
71+
}
72+
73+
// method
74+
func (dikdortgen Dikdortgen) Alan() float64 {
75+
return dikdortgen.genislik * dikdortgen.yukseklik
76+
}
77+
78+
func main() {
79+
daire1 := Daire{10}
80+
daire2 := Daire{25}
81+
dikdortgen1 := Dikdortgen{9, 4}
82+
dikdortgen2 := Dikdortgen{12, 2}
83+
84+
fmt.Println("daire1 in alanı: ", daire1.Alan())
85+
fmt.Println("daire2 nin alanı: ", daire2.Alan())
86+
fmt.Println("dikdortgen1 in alanı: ", dikdortgen1.Alan())
87+
fmt.Println("dikdortgen2 nin alanı: ", dikdortgen2.Alan())
88+
}
89+
```
90+
91+
Methodları kullanma notları.
92+
93+
- Methodların adı aynıysa ancak aynı alıcıları paylaşmıyorlarsa, aynı değildirler.
94+
- Methodlar alıcılardaki alanlara erişebilirler.
95+
- Bir `struct` da method çağırmak için `.` kullanın, aynı şekilde alanları da çağırabilirsiniz.
96+
97+
![](images/2.5.shapes_func_with_receiver_cp.png?raw=true)
98+
99+
Figure 2.9 Methodlar farklı struct larda farklıdırlar.
100+
101+
Yukarıdaki örnakte Alan() methodu hem Dikdortgen hem de Daire'de mevcuttur, bu nedenle alıcıları Dikdortgen ve Daire'dir.
102+
103+
One thing that's worth noting is that the method with a dotted line means the receiver is passed by value, not by reference. The difference between them is that a method can change its receiver's values when the receiver is passed by reference, and it gets a copy of the receiver when the receiver is passed by value.
104+
105+
Alıcı sadece bir struct'mı olmalıdır? Tabii ki değil. Herhangibir tür/tip methodun alıcısı olabilir. Özelleştirilmiş türler/tipler hakkında kafanız karışabilir. struct özel bir tür/tip dir - daha birçok özelleştirilmiş tür/tip yer almaktadır.
106+
107+
Özelleştirilmiş bir tür/tip tanımlamak için aşağıdaki formatı kullanın.
108+
```Go
109+
type typeName typeLiteral
110+
```
111+
Özelleştirilmiş türler/tipler e örnekler:
112+
113+
```Go
114+
type yas int
115+
type fiyat float32
116+
type aylar map[string]int
117+
118+
a := aylar {
119+
"Ocak":31,
120+
"Şubat":28,
121+
...
122+
"Aralık":31,
123+
}
124+
```
125+
126+
Özelleştirilmiş türlerin/tiplerin artık nasıl kullanılacağını biliyorsunuz. C programlama dilindeki `typedef` ifadesine benzer bir şekilde, yukarıdaki örnekte `int` yerine `yas` kullanıyoruz.
127+
128+
`method` hakkında konuşmaya geri dönelim.
129+
130+
Özelleştirilmiş türler/tipler de istediğiniz kadar method kullanabilirsiniz.
131+
```Go
132+
package main
133+
134+
import "fmt"
135+
136+
const (
137+
BEYAZ = iota
138+
SIYAH
139+
MAVI
140+
KIRMIZI
141+
SARI
142+
)
143+
144+
type Kutu struct {
145+
genislik, yukseklik, derinlik float64
146+
renk Renk
147+
}
148+
type Renk byte
149+
type KutuListesi []Kutu //kutu listesi
150+
151+
// method
152+
func (kutu Kutu) Hacim() float64 {
153+
return kutu.genislik * kutu.yukseklik * kutu.derinlik
154+
}
155+
156+
// işaretçi alıcılı method
157+
func (k *Kutu) RenkAta(r Renk) {
158+
k.renk = r
159+
}
160+
161+
// method
162+
func (kl KutuListesi) EnBuyuklerininRengi() Color {
163+
h := 0.00
164+
r := Renk(BEYAZ)
165+
for _, k := range kl {
166+
if k.Hacim() > h {
167+
h = k.Hacim()
168+
r = k.renk
169+
}
170+
}
171+
return k
172+
}
173+
174+
// method
175+
func (kl KutuListesi) SiyahaBoya() {
176+
for i, _ := range kl {
177+
kl[i].RenkAta(SIYAH)
178+
}
179+
}
180+
181+
// method
182+
func (r Renk) String() string {
183+
strings := []string{"BEYAZ", "SIYAH", "MAVI", "KIRMIZI", "SARI"}
184+
return strings[r]
185+
}
186+
187+
func main() {
188+
kutular := KutuListesi{
189+
Kutu{4, 4, 4, KIRMIZI},
190+
Kutu{10, 10, 1, SARI},
191+
Kutu{1, 1, 20, SIYAH},
192+
Kutu{10, 10, 1, MAVI},
193+
Kutu{10, 30, 1, BEYAZ},
194+
Kutu{20, 20, 20, SARI},
195+
}
196+
197+
fmt.Printf("%d adet kutumuz var\n", len(kutular))
198+
fmt.Println("İlk kutunun hacmi ", kutular[0].Hacim(), "cm³")
199+
fmt.Println("Son kutunun rengi", kutular[len(kutular)-1].renk.String())
200+
fmt.Println("En büyük kutu", kutular.EnBuyuklerininRengi().String())
201+
202+
// Hepsini siyaha boyayalım
203+
boxes.SiyahaBoya()
204+
205+
fmt.Println("İkinci kutunun rengi", kutular[1].renk.String())
206+
fmt.Println("En büyüğü", kutular.EnBuyuklerininRengi().String())
207+
}
208+
```
209+
210+
Bazı sabitleri ve özelleştirilmiş tür/tipleri tanımlarız
211+
212+
- `Renk` 'i `byte` 'ın takma adı olarak kullanın.
213+
- Hacim, yukseklik, genislik, derinlik ve renk alanlarını içeren `Kutu` struct ını tanımlayın.
214+
- `Kutu` yu alanı olarak alan `KutuListesi` strruct ı tanımlayın.
215+
216+
Daha sonra özelleştirilmiş türlerimiz/tiplerimiz için bazı methodlar tanımladık.
217+
218+
- `Hacim()` uses Kutu as its receiver and returns the volume of Kutu.
219+
- `RenkAta(c Color)` changes Box's color.
220+
- `EnBuyuklerininRengi()` returns the color which has the biggest volume.
221+
- `SiyahaBoya()` sets color for all Box in KutuListesi to SIYAH.
222+
- `String()` use Color as its receiver, returns the string format of color name.
223+
224+
Is it much clearer when we use words to describe our requirements? We often write our requirements before we start coding.
225+
226+
### Use pointer as receiver
227+
228+
Let's take a look at `RenkAta` method. Its receiver is a pointer of Box. Yes, you can use `*Box` as a receiver. Why do we use a pointer here? Because we want to change Box's color in this method. Thus, if we don't use a pointer, it will only change the value inside a copy of Box.
229+
230+
If we see that a receiver is the first argument of a method, it's not hard to understand how it works.
231+
232+
You might be asking why we aren't using `(*b).Color=c` instead of `b.Color=c` in the `RenkAta()` method. Either one is OK here because Go knows how to interpret the assignment. Do you think Go is more fascinating now?
233+
234+
You may also be asking whether we should use `(&bl[i]).RenkAta(SIYAH)` in `SiyahaBoya` because we pass a pointer to `RenkAta`. Again, either one is OK because Go knows how to interpret it!
235+
236+
### Inheritance of method
237+
238+
We learned about inheritance of fields in the last section. Similarly, we also have method inheritance in Go. If an anonymous field has methods, then the struct that contains the field will have all the methods from it as well.
239+
```Go
240+
package main
241+
242+
import "fmt"
243+
244+
type Human struct {
245+
name string
246+
age int
247+
phone string
248+
}
249+
250+
type Student struct {
251+
Human // anonymous field
252+
school string
253+
}
254+
255+
type Employee struct {
256+
Human
257+
company string
258+
}
259+
260+
// define a method in Human
261+
func (h *Human) SayHi() {
262+
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
263+
}
264+
265+
func main() {
266+
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
267+
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
268+
269+
sam.SayHi()
270+
mark.SayHi()
271+
}
272+
```
273+
### Method Overriding
274+
275+
If we want Employee to have its own method `SayHi`, we can define a method that has the same name in Employee, and it will hide `SayHi` in Human when we call it.
276+
```Go
277+
package main
278+
279+
import "fmt"
280+
281+
type Human struct {
282+
name string
283+
age int
284+
phone string
285+
}
286+
287+
type Student struct {
288+
Human
289+
school string
290+
}
291+
292+
type Employee struct {
293+
Human
294+
company string
295+
}
296+
297+
func (h *Human) SayHi() {
298+
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
299+
}
300+
301+
func (e *Employee) SayHi() {
302+
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
303+
e.company, e.phone) //Yes you can split into 2 lines here.
304+
}
305+
306+
func main() {
307+
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
308+
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
309+
310+
sam.SayHi()
311+
mark.SayHi()
312+
}
313+
314+
```
315+
You are able to write an Object-oriented program now, and methods use rule of capital letter to decide whether public or private as well.
316+
317+
## Links
318+
319+
- [Rehber](preface.md)
320+
- Önceki bölüm: [struct](02.4.md)
321+
- Sonraki bölüm: [interface](02.6.md)

0 commit comments

Comments
 (0)