Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Scala: Object và Companion Object
Đây là bài thứ 2 trong series. Bài trước là về Class và Method. Bạn nên đọc tuần tự để hiểu tốt hơn.
Object
Trong Scala, tất cả mọi giá trị đều là một object, tất cả mọi method đều trực thuộc một object nào đó.
Khi trong Java bạn thường thấy các property và method được gán nhãn static
trong một class thì trong Scala việc đó trở nên không cần thiết. Trong Scala chúng ta có thể dùng từ khóa object
để định nghĩa một khoảng không gian với một tên gọi nhất định giống như là một "singleton object". Tất cả những thứ nằm trong phần không gian nói trên cũng là một object, vì vậy hoàn toàn có thể định nghĩa method và property ở trong này.
Định nghĩa hơi loằng còn nhà bà ngoằng đúng không Tóm gọn lại thì chúng ta có một cú pháp , thể hiện bằng từ khóa
object
mà
- Có thể đặt các utility method hoặc global property trong này (giống khoảng bên trong
static
ở Java). - Có thể đặt các factory method cho object.
- Sử dụng như là Singleton Pattern (Cái này là một design pattern cơ bản nhé).
Ở trên thì lý do thứ 3 là có tồn tại tuy nhiên chẳng dùng bao giờ mấy, vì vậy nếu bạn vẫn lăn tăn về Singleton Pattern thì có thể bỏ qua và ko cần nhớ.
Cách khai báo Object cũng không khác class là mấy
object obj_name extends class_name with trait_name1 with trait_name2 {
}
Scala có một object tên là Predef được định nghĩa là import sẵn. Ví dụ hàm println()
thực ra là một method của object Predef.
Sau đây mình sẽ đưa ra một ví dụ tạo object trùng tên với một class.
class Saiyan(val name: String, val age: Int)
object Saiyan {
def apply(name: String, age: Int): Saiyan = new Saiyan(name, age)
}
apply
là một hàm đặc biệt. Sau khi định nghĩa như trên thì 2 dòng dưới đây là như nhau
Saiyan.apply("goku", 100)
Saiyan("goku",100)
So với cách gọi trực tiếp new Saiyan("goku", 100)
thì viết thông qua object thế này có 2 cái lợi
- Ẩn được nội dung cụ thể của class
Saiyan
- Có thể trả về một instance của một subclass của
Saiyan
.
Cách viết như trên còn có thể viết gọn nữa như sau
case class Saiyan(name: String, age: Int)
Vậy case class
là gì ?
Case class
Case class
là một đối tượng có 2 cách dùng. Cách dùng thứ 1 mình sẽ trình bày sau đây và cách dùng thứ 2 là trong Pattern Matching mà chúng ta sẽ gặp trong một phần khác.
Case class
mang bên trong mình một class cùng tên với các constructor parameter đều là công khai (public). Ngoài ra mang thêm những method cơ bản của một object.
Thế nào là những method cơ bản của một object ?
equals()
hashCode()
toString()
case class Saiyan(name: String, age: Int)
Saiyan("goku",100).equals(Saiyan("goku",100)) // true
Companion Object
Object trùng tên với class như bên trên được gọi là Companion Object. Companion Object khác biệt với Object bình thường ở chỗ: có thể truy cập ngay cả những property hay method là private
class Saiyan(val name: String, private val age: Int)
object Saiyan {
def apply(name: String, age: Int): Saiyan = {
val s = new Saiyan(name, age)
println(s.age) // OK
return s
}
}
Nếu object mang một cái tên khác, nó sẽ không còn được coi là companion object và đoạn code trên sẽ ko chạy. Bạn thử sửa object Saiyan
thành object Namek
chẳng hạn xem nhé! Lưu ý là khi chạy đoạn code trên trên scala intepreter thì cần bật paste mode lên (gõ :paste
, paste rồi Ctrl+D).
Đến đây có thể bạn sẽ nghĩ, nếu đến private
của class mà Companion Object còn đọc được thì có gì mà Companion Object không đọc được nữa đâu ?
Câu trả lời là private[this]
. Nếu gắn private[this]
vào trước một property/method thì nó sẽ chỉ được nhìn thấy duy nhất bên trong class đó.
Phần tiếp theo là Trait.







