Scala: Class và Method
Class
Mình sẽ mặc định là bạn hiểu class là gì, và class trong Java như thế nào rồi nhé.
Ngoài sự khác nhau về cú pháp ra thì về cơ bản class trong Scala không khác gì một class trong Java. Khi khai báo class trong Scala thì bạn có thể viết tất cả parameter của constructor vào câu khai báo và bên trong thì không cần viết lại constructor nữa.
// Inside constructor parameters
class Saiyan(n: String, a: Int) {
val name = n;
val age = a
}
// Direct constructor parameters
class Saiyan(val name: String, val age: Int)
Ở cách thứ 2 thì từ khóa val hay var cho phép định nghĩa luôn parameter trong câu khai báo.
Class trong Scala có một điểm cần chú ý. Với mỗi class về cơ bản chỉ được có một constructor duy nhất, Mặc dù về mặt cú pháp bạn vẫn có thể định nghĩa nhiều constructor nhưng thực tế sử dụng thì chỉ trong những trường hợp rất đặc biệt. Thêm nữa, constructor đầu tiên có một ý nghĩa đặc biệt hơn các constructor khác (nếu được định nghĩa) và được gọi là primary constructor.
Parameter được định nghĩa với từ khóa val hoặc var như cách 2 là công khai với phạm vi ngoài class, và tất nhiên cả với các method bên trong class nữa.
class Saiyan(val name: String, val age: Int) {
def (p: Saiyan): Saiyan = {
new Saiyan(name p.name, age p.age)
}
}
val goku = new Saiyan("Goku", 100)
val vegeta = new Saiyan("Vegeta",100)
val vegeto = goku vegeta
vegeto.name
// res0: String = GokuVegeta
vegeto.age
// res1: Int = 200
Nếu bạn muốn thử hãy cài Scala vào máy, bật scala interpreter lên và paste đoạn code trên vào nhé.
Method
Ở bên trên bạn đã thấy một method được định nghĩa trong class Person, tên là. Method trong Scala có thể định nghĩa trực tiếp bằng dấu = và không thông qua ký tự đóng mở ngoặc {}. Tuy vậy, dùng đóng mở ngoặc vẫn là cách phổ thông hơn.
class Person(val name: String, val age: Int) {
def (p: Person): Person = new Person(name p.name, age p.age)
}
Trước mỗi method có thể được thêm private, protected, private[this], protected[package_name].
• private: method chỉ có thể truy cập từ bên trong class.
• protected: method chỉ có thể truy cập từ bên trong class và các class con kế thừa nó.
• private[this]: method chỉ có thể truy cập từ bên trong object (cái này sẽ nói sau trong phần object).
• protected[package_name]: method có thể truy cập từ bên trong package có tên là package_name.
• Method không có gì ở đầu thì mặc định là public, tức là có thể truy cập ở bất cứ đâu.
Curry method
Method trong Scala có thể có nhiều dãy parameter, mỗi dãy được viết trong ngoặc đơn (). Method kiểu này gọi là curry method, là một kỹ thuật thông dụng trong các ngôn ngữ lập trình hàm và cần thiết cho phần implicit parameter sẽ được trình bày sau. Method union dưới đây là một curry method.
class Fusion {
def union(left: Saiyan)(right: Saiyan): Saiyan = left right
}
var magic = new Fusion()
// magic: Fusion = Fusion@447a020
val vegeto = magic.union(goku)(vegeta)
// magic: Fusion = Fusion@447a020
magic.union(goku) _
// res3: Saiyan => Saiyan =
Ở dòng cuối cùng, khi chỉ gọi một dãy parameter thì curry method sẽ trả về một function.
Property
Property là một phần không thể thiếu của class. Property có thể là private hoặc protected. Nếu không viết gì đằng trước thì property là public.
Trước property trong class có thể dùng từ khóa val cho trường hợp không thể thay đổi giá trị, và var cho trường hợp có thể thay đổi giá trị.
Kế thừa
Tính chất quan trọng nhất của class là tính kế thừa. Kế thừa trong Java có 2 loại: kế thừa class cha (từ khóa extends) và kế thừa interface (từ khóa implements). Mỗi class chỉ có thể kế thừa duy nhất một class cha duy nhất.
Trong Scala tính kế thừa đã được phát triển thêm. Một class có thể kế thừa nhiều trait khác nhau. Trait sẽ được nói đến trong một phần khác. Ở đây chúng ta sẽ chỉ nói đến kế thừa class thông dụng.
class Saiyan(val strength: Int) {
def recover(): Unit = {
println(strength*10)
}
}
val kakarot = new Saiyan(10)
kakarot.recover() // 100
class SuperSaiyan(strength: Int) extends Saiyan(strength) {
override def recover(): Unit = {
println(strength*100)
}
}
val goku = new SuperSaiyan(10)
goku.recover() // 1000
Nếu trong đoạn code trên mà thiếu override khi viết class SuperSaiyan thì lập tức compiler sẽ báo lỗi, điều này làm giảm thiểu lỗi khai báo lại method xảy ra ngoài ý muốn như ở JavaScript.
>> Tìm hiểu thêm: Infix operator với Type trong Scala