Skip to content

Commit f17e295

Browse files
committed
update /th/tour/traits page
1 parent b8e1b21 commit f17e295

File tree

1 file changed

+136
-11
lines changed

1 file changed

+136
-11
lines changed

_th/tour/traits.md

+136-11
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,59 @@ next-page: tuples
1111
previous-page: classes
1212
---
1313

14-
Trait ใช้เพื่อแชร์ interface และ field ระหว่างคลาส มันจะเหมือนกับ interface ใน Java 8
15-
คลาส และ object สามารถขยาย trait ได้แต่ trait ไม่สามารถ instant เป็น object และไม่สามารถมี parameter ได้
14+
Trait ใช้เพื่อแชร์ interface และ field ระหว่างคลาส โดยที่ trait จะคล้ายกับ interface ใน Java 8\
15+
คลาส และ object สามารถ extend trait ได้ แต่เราไม่สามารถสร้าง object จาก trait ได้\
16+
ดังนั้น trait จึงไม่สามารถมี parameter เช่นเดียวกับที่คลาสมี
17+
18+
## การกำหนด Trait
1619

17-
## การกำหนด trait
1820
วิธีที่ง่ายที่สุดในการกำหนด trait คือการประกาศด้วย keyword `trait` และ indentifier:
1921

22+
{% tabs trait-hair-color %} {% tab 'Scala 2 and 3' for=trait-hair-color %}
23+
2024
```scala mdoc
2125
trait HairColor
2226
```
27+
28+
{% endtab %} {% endtabs %}
29+
2330
trait จะมีประโยชน์อย่างยิ่งด้วยการเป็น generic type และเป็น abstract method
31+
32+
{% tabs trait-iterator-definition class=tabs-scala-version %}
33+
34+
{% tab 'Scala 2' for=trait-iterator-definition %}
35+
2436
```scala mdoc
2537
trait Iterator[A] {
2638
def hasNext: Boolean
2739
def next(): A
2840
}
2941
```
3042

31-
การขยาย `trait Iterator[A]` ต้องการ type `A` และ implementation ของ method `hasNext` และ `next`
43+
{% endtab %}
44+
45+
{% tab 'Scala 3' for=trait-iterator-definition %}
46+
47+
```scala
48+
trait Iterator[A]:
49+
def hasNext: Boolean
50+
def next(): A
51+
```
52+
53+
{% endtab %}
54+
55+
{% endtabs %}
56+
57+
การขยาย (extend) `trait Iterator[A]` ต้องการ type `A` และ implementation ของ method `hasNext` และ `next`
58+
59+
## การใช้ Trait
60+
61+
ใช้ keyword `extends` เพื่อขยาย trait จากนั้นให้ implement abstract member ใดๆ ของ trait โดยใช้ keyword `override`:
62+
63+
{% tabs trait-intiterator-definition class=tabs-scala-version %}
64+
65+
{% tab 'Scala 2' for=trait-intiterator-definition %}
3266

33-
## การใช้ traits
34-
ใช้ keyword `extends` เพื่อขยาย trait ดังนั้นจะ implement abstract member ใดๆ ของ trait โดยใช้ keyword `override`:
3567
```scala mdoc:nest
3668
trait Iterator[A] {
3769
def hasNext: Boolean
@@ -55,10 +87,75 @@ val iterator = new IntIterator(10)
5587
iterator.next() // returns 0
5688
iterator.next() // returns 1
5789
```
58-
คลาส `IntIterator` นี้รับค่า parameter `to` เป็น upper bound มัน `extends Iterator[Int]` ซึ่งหมายความว่า method `next` จะต้อง return เป็น Int
5990

60-
## Subtyping
61-
ในเมื่อ trait ที่ให้มานั้น required, subtype ของ trait สามารถถูกใช้แทนที่ได้
91+
{% endtab %}
92+
93+
{% tab 'Scala 3' for=trait-intiterator-definition %}
94+
95+
```scala
96+
trait Iterator[A]:
97+
def hasNext: Boolean
98+
def next(): A
99+
100+
class IntIterator(to: Int) extends Iterator[Int]:
101+
private var current = 0
102+
override def hasNext: Boolean = current < to
103+
override def next(): Int =
104+
if hasNext then
105+
val t = current
106+
current += 1
107+
t
108+
else
109+
0
110+
end IntIterator
111+
112+
val iterator = new IntIterator(10)
113+
iterator.next() // returns 0
114+
iterator.next() // returns 1
115+
```
116+
117+
{% endtab %}
118+
119+
{% endtabs %}
120+
121+
คลาส `IntIterator` นี้รับค่า parameter `to` เพื่อกำหนดค่าสูงสุด (upper bound) โดยที่คลาส `IntIterator` ได้ extend จาก `Iterator[Int]`\
122+
ดังนั้น method `next` จะต้อง return ค่าเป็น Int
123+
124+
## การใช้ Subtype
125+
126+
เมื่อจำเป็นต้องใช้ trait ใดๆ เราสามารถใช้ subtype (คลาสใดก็ตาม ที่ extend มาจาก trait นั้นๆ) แทนได้
127+
128+
> ***Note by Thai translator:***\
129+
> "เมื่อจำเป็นต้องใช้ trait ใดๆ" ในที่นี้ น่าจะหมายถึงเรามีการระบุไว้ว่า parameter ที่ได้ระบุ type เป็น trait\
130+
> ดังนั้นเราสามารถใช้ **subtype ใดๆ ที่ implement จาก trait นั้นๆ ได้**
131+
>
132+
> **ลองพิจารณา code นี้:**
133+
>
134+
> ```scala
135+
> val dog = new Dog("Harry") // คลาส `Dog` เป็น subtype ของ trait `Pet`
136+
>
137+
> // parameter `pet` มี type เป็น trait `Pet`
138+
> def getPetName(pet: Pet): String = pet.name
139+
>
140+
> getPetName(dog)
141+
> ```
142+
>
143+
> ถ้าอิงจากตัวอย่างจาก code block ด้านล่าง เราจะเห็นได้ว่า code ด้านบน\
144+
> เราส่งตัวแปร `dog` ซึ่งเป็น instance ของคลาส `Dog` ไปให้ function `getPetName`\
145+
> โดยที่คลาส `Dog` ก็เป็น subtype ของ trait `Pet` อีกทีหนึ่ง
146+
147+
{% tabs trait-pet-example class=tabs-scala-version %}
148+
149+
{% tab 'Scala 2' for=trait-pet-example %}
150+
151+
{% tabs trait-pet-example class=tabs-scala-version %}
152+
153+
{% tab 'Scala 2' for=trait-pet-example %}
154+
155+
{% tabs trait-pet-example class=tabs-scala-version %}
156+
157+
{% tab 'Scala 2' for=trait-pet-example %}
158+
62159
```scala mdoc
63160
import scala.collection.mutable.ArrayBuffer
64161
@@ -76,6 +173,34 @@ val animals = ArrayBuffer.empty[Pet]
76173
animals.append(dog)
77174
animals.append(cat)
78175
animals.foreach(pet => println(pet.name)) // แสดงค่า Harry Sally
176+
79177
```
80-
`trait Pet` มี abstract field `name` ซึ่ง implement โดย Cat และ Dog ใน constructor ของมัน
81-
ในบรรทัดสุดท้าย เราเรียก `pet.name` ซึ่งจะต้องถูก implement แล้วใน subtype ใดๆ ของ trait `Pet`
178+
179+
{% endtab %}
180+
181+
{% tab 'Scala 3' for=trait-pet-example %}
182+
183+
```scala
184+
import scala.collection.mutable.ArrayBuffer
185+
186+
trait Pet:
187+
val name: String
188+
189+
class Cat(val name: String) extends Pet
190+
class Dog(val name: String) extends Pet
191+
192+
val dog = Dog("Harry")
193+
val cat = Cat("Sally")
194+
195+
val animals = ArrayBuffer.empty[Pet]
196+
animals.append(dog)
197+
animals.append(cat)
198+
animals.foreach(pet => println(pet.name)) // แสดงค่า Harry Sally
199+
```
200+
201+
{% endtab %}
202+
203+
{% endtabs %}
204+
205+
`trait Pet` มี abstract field `name` ซึ่ง implement ไว้ใน constructor ของคลาส `Cat` และ `Dog`\
206+
ในบรรทัดสุดท้าย เราเรียกใช้ `pet.name` ซึ่งได้มีการ implement `name` ไว้ใน subtype ใดๆ ของ trait `Pet` แล้ว

0 commit comments

Comments
 (0)