1. Giới thiệu về Kotlin

Kotlin là một ngôn ngữ ngữ dụng kiểu tĩnh dành cho Java Virtual Machine đã chính thức phát hành phiên bản 1.0. Nó được tạo ra bởi JetBrains, Kotlin cũng giống như nhiều ngôn ngữ lập trình không phải Java khác, tức là cũng sẽ chạy trên JVM và sử dụng các công cụ và thư viện hiện có của Java. Và ngược lại Java cũng có thể sử dụng các item được xây dựng trong Kotlin.

Theo website JetBrains, mục tiêu quan trọng của Kotlin là tính hữu dụng. Từ lúc giới thiệu vào năm 2011 cho đến khi phát hành phiên bản 1.0, JetBrains đã luôn chú trọng đến tính tương hợp với Java..Mặc dù Kotlin có một số tính năng hoàn toàn mới chẳng hạn như một type system được thiết kế để ngăn chặn các bug như các null pointer reference, nhưng quan trọng là nó làm việc cùng với code và cơ sở hạ tầng hiện có của Java. Cuối cùng, Kotlin không có trình quản lý gói và build system của riêng nó, do Java đã có sẵn.

2. Kotlin và Android

Lập trình Android là một trong những lĩnh vực quan trọng mà JetBrains hướng đến với Kotlin. Ngôn ngữ mang đến tính tương thích ngược với Java 6 và 7, các phiên bản của Java hầu hết đều tương thích chặt chẽ với Android. JetBrains cũng hy vọng Kotlin sẽ được sử dụng trong các lĩnh vực khác chẳng hạn như các ứng dụng lớn và phức tạp, đề cao hiệu suất.

Các nhà phát triển không có lựa chọn thay thế cho việc phát triển ứng dụng Android bằng ngôn ngữ Java. Mặc dù được sử dụng rộng rãi, nhưng trong quá trình hoạt động ngôn ngữ Java sinh ra rất nhiều file rác. Java 8 đã giải quyết một số vấn đề ngôn ngữ và đặc biệt hơn là với Java 10. Để có được nhiều lợi ích từ việc chỉnh sửa trong hai phiên bản này, bạn phải đặt SDK tối thiểu sang Android 24 chỉ để sử dụng Java 8. Kotlin nhắm đến việc lấp đầy khoảng trống đó của một ngôn ngữ hiện đại đang thiếu cho nền tảng Android.

Có một vài nguyên lý cốt lõi mà giúp Kotlin tồn tại đó là:

Nhỏ gọn để giảm số lượng mã boilerplate cần viết. Mã code dễ đọc và dễ hiểu hơn. An toàn, tránh toàn bộ các lớp lỗi như các null pointer exceptions. Linh hoạt cho việc xây dựng ứng dụng phía máy chủ, ứng dụng Android hoặc mã lối vào đang chạy trong trình duyệt. Khả năng tương tác để tận dụng các khuôn khổ và thư viện hiện có của JVM với khả năng tương tác Java 100%.

3. Ưu và nhược điểm của Kotlin

3.1. Ưu điểm

Dù không thiếu các ngôn ngữ biên dịch sang Java bytecode, nhưng có một vài yếu tố làm cho Kotlin nổi bật hơn cả:

Có thể thay thế cho Java

Một trong những thế mạnh lớn nhất của Kotlin như là một ứng viên để thay thế cho Java là khả năng tương tác rất tốt giữa Java và Kotlin—bạn có thể thậm chí có code Java và Kotlin tồn tại song song trong cùng dự án, và tất cả mọi thứ vẫn sẽ được biên dịch một cách hoàn hảo. Dưới đây, bạn có thể thấy một ví dụ về một dự án bao gồm một Activity Java và một Actitivy Kotlin.

Trong thực tế, một khi dự án kết hợp Kotlin và Java được biên dịch, người dùng sẽ không thể biết những phần nào của dự án của bạn được viết bằng Java, và những phần nào được viết bằng Kotlin. Bởi vì các lớp Kotlin và Java có thể tồn tại song song trong cùng một dự án, nên có thể bắt đầu sử dụng Kotlin mà không cần phải làm bất cứ điều gì to tát cả giống như chuyển đổi toàn bộ dự án sang Kotlin hoặc bắt đầu một dự án mới để bạn có thể thử Kotlin.

Vì Kotlin là hoàn toàn tương thích với Java, nên cũng có thể sử dụng phần lớn các thư viện Java và các framework trong dự án Kotlin của bạn—thậm chí nâng cao các framework dựa vào chú thích xử lý.

Dễ học

Kotlin nhằm mục đích là nâng cao hơn so vớiJava, chứ không phải hoàn toàn viết lại, rất nhiều các kỹ năng đã có trong việc code Java của bạn vẫn được áp dụng đối với dự án Kotlin.

Kotlin cũng được thiết kế để có thể dễ học cho các nhà phát triển Java. Những nhà phát triển Java sẽ cảm thấy rằng hầu hết cú pháp của Kotlin đều quen thuộc; ví dụ, các code được sử dụng để tạo ra một lớp mới trong Kotlin là rất giống với Java:

class MainActivity : AppCompatActivity() {

Kotlin cũng được thiết kế trực quan và dễ đọc, do đó, ngay cả khi bạn gặp một số code khác biệt, thì bạn vẫn có thể để biết được ý nghĩa về những gì code này làm.

Kết hợp những gì tốt nhất của lập trình hàm và thủ tục

Hiện đang có một số lý thuyết lập trình được sử dụng rộng rãi, nhưng khi nói đến các câu hỏi về “phương pháp nào là tốt nhất”, thì không dễ để có câu trả lời. Mỗi kiểu lập trình có tập hợp điểm mạnh và điểm yếu của nó, do đó, mặc dù không thiếu các kịch bản mà lập trình hàm có một lợi thế, thì cũng có rất nhiều vấn đề nơi mà một cách tiếp cận lập trình thủ tục sẽ hiệu quả hơn.

Vậy tại sao bạn cần phải lựa chọn giữa hàm và thủ tục? Giống như nhiều ngôn ngữ lập trình hiện đại khác, Kotlin nhằm mục đích mang lại cho bạn những gì tốt nhất của cả hai bằng cách kết hợp các khái niệm và các yếu tố của lập trình thủ tục và hàm.

Android Studio hỗ trợ

Kotlin được phát triển bởi JetBrains, công ty đứng sau IntelliJ—IDE mà Android Studio dựa trên nó. Không có gì bất ngờ, rằng Android Studio hỗ trợ tốt cho Kotlin. Một khi bạn đã cài đặt plugin Kotlin, Android Studio làm cho việc cấu hình Kotlin trong dự án của bạn trở nên đơn giản giống như mở một vài menu.

Một khi bạn đã thiết lập plugin Kotlin cho Android Studio, IDE của bạn sẽ không gặp vấn đề gì việc hiểu, biên dịch và chạy code Kotlin. Android Studio cũng cung cấp việc gỡ lỗi, tự động hoàn tác, điều hướng code, unit testing, và tái cấu trúc cho Kotlin.

Một khi dự án Android Studio của bạn đã được cấu hình để hỗ trợ cho Kotlin, bạn thậm chí có thể chuyển đổi toàn bộ một tập tin mã nguồn Java thành một tập tin Kotlin, với chỉ một vài cú nhấp chuột.

Code ngắn gọn hơn

Nếu bạn so sánh một lớp Java và một lớp Kotlin cho ra cùng một kết quả, thì cái được viết trong Kotlin thường sẽ gọn gàng hơn nhiều và nhỏ gọn hơn so với những gì được viết bằng Java. Và như mọi nhà phát triển đều biết, code ít hơn có nghĩa là ít lỗi hơn!

Ví dụ, các code Java sau tạo ra một Activity bao gồm một floating action button (FAB), mà khi chạm vào, hiển thị một snackbar có chứa các thông báo hữu ích This is a snackbar.

public class MainActivity extends AppCompatActivity {
 
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
       setSupportActionBar(toolbar);
 
       FloatingActionButton myfab = (FloatingActionButton) findViewById(R.id.myfab);
       myfab.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
               Snackbar.make(view, "This is a snackbar", Snackbar.LENGTH_LONG)
                       .setAction("Action", null).show();
           }
       });
   }
}

Kotlin đạt được điều tương tự bằng lượng code ít hơn, đặc biệt là khi nói đến việc tạo FAB và thiết lập onClickListener:

class MainActivity : AppCompatActivity() {
 
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
       val toolbar = findViewById(R.id.toolbar) as Toolbar
       setSupportActionBar(toolbar)
 
       val myfab = findViewById(R.id.myfab) as FloatingActionButton
       myfab.setOnClickListener { view ->
           Snackbar.make(view, "This is a snackbar", Snackbar.LENGTH_LONG)
                   .setAction("Action", null).show()
       }
   }
}

Cả hai đoạn code cho ra kết quả giống nhau:

Kotlin đặc biệt tốt trong việc giảm số lượng code mà bạn cần phải viết, làm cho việc viết code trong Kotlin trở thành một trải nghiệm thú vị hơn nhiều, so với việc viết code trong nhiều ngôn ngữ khác như Java.

Đặc biệt, các extension của Kotlin Android (mà chúng ta sẽ khám phá trong phần hai) cho phép bạn nhập tham chiếu đến một View vào một tập tin Activity, từ đó, bạn có thể làm việc với giao diện như thể nó là một phần của Activity đó. Điều này có nghĩa là bạn không còn phải xác định mỗi View bằng cách sử dụng findViewById, mà có thể chuyển đổi code chẳng hạn như:

TextView text = (TextView) findViewById(R.id.myTextView); text.setText("Hello World");

Thành gọn gàng hơn nhiều:

myTextView.setText("Hello World")

3.2. Nhược điểm

Không có ngôn ngữ lập trình nào là hoàn hảo cả, do đó, mặc dù Kotlin có rất nhiều thứ để cung cấp cho các nhà phát triển Android, nó vẫn có một số nhược điểm mà bạn cần lưu ý:

Thêm thời gian chạy Runtime

Thư viện tiêu chuẩn của Kotlin và runtime sẽ làm tăng kích thước tập tin .apk của bạn. Mặc dù nó chỉ tương đương với khoảng 800KB, nhưng nếu ứng dụng của bạn đã lớn sẵn rồi thì 800KB phụ có thể làm nó phình to và khiến người dùng nghĩ lại trước khi tải về ứng dụng của bạn.

Không hẳn là code dễ đọc đối với beginer

Mặc dù cú pháp ngắn gọn của Kotlin là một trong những thế mạnh lớn nhất của ngôn ngữ, nhưng bạn có thể thấy một số khó khăn ban đầu, đơn giản bởi vì có rất nhiều thứ đang được thực hiện trong một số lượng nhỏ code đó. Java có thể dài dòng hơn, nhưng ngược lại tất cả mọi thứ đều rõ ràng, có nghĩa là những người không quen code Java có xu hướng dễ dàng hơn để hiểu so Kotlin.

Ngoài ra, nếu sử dụng không hợp lý, quá tải toán tử của Kotlin có thể dẫn đến số code đó có thể khó khăn để đọc.

Thiếu hỗ trợ chính thức

Kotlin có thể được trợ tốt trong Android Studio, nhưng cần ghi nhớ rằng Kotlin không được xác nhận chính thức là của Google.

Ngoài ra, tính năng tự động hoàn tác và biên dịch trong Android Studio có xu hướng chạy hơi chậm khi bạn làm việc với Kotlin so với một dự án thuần Java.

Cộng đồng nhỏ hơn và ít có sẵn trợ giúp

Vì Kotlin là một ngôn ngữ tương đối mới, nên cộng đồng Kotlin vẫn còn khá nhỏ, đặc biệt là so với cộng đồng của ngôn ngữ khác như Java. Nếu bạn chuyển đổi sang Kotlin, thì bạn có thể không có được truy cập vào cùng một số hướng dẫn, bài đăng trên blog, và tài liệu hướng dẫn sử dụng, và có thể gặp ít hỗ trợ từ cộng đồng về những nơi như các diễn đàn và Stack Overflow. Tại thời điểm bài viết, tìm kiếm cho Kotlin trong Stack Overflow trả về các bài viết chỉ hơn 4.600 được dán nhãn Kotlin—so với hơn 1.000.000 bài viết có chứa các từ khóa Java.

4. Đặc điểm

4.1. Khai báo biến

  • Có 2 từ khóa khai báo biến trong Kotlin là var và val
val a: Int = 1
val b = 1   // `Int` type is inferred
val c: Int  // Type required when no initializer is provided
c = 1       // definite assignment
var x = 5 // `Int` type is inferred
x += 1
  • Từ khóa var sử dụng khi giá trị của biến thay đổi, val sử dụng khi giá trị của biến không thay đổi
  • Từ khóa val giống như readonly trong C# hoặc final trong Java
  • Biến val phải được khởi tạo lúc khai báo
  • Từ khóa Void trong java hay C# sẽ được thay thế bằng Unit trong Kotlin

4.2. Null Safety

Một trong những cạm bẫy phổ biến trong các ngôn ngữ lập trình, bao gồm cả Java là cho phép 1 thành phần nào đó được Null. Nếu không chắc chắn thành phần đó được phép Null hay không sẽ rất dễ xảy ra lỗi không lường trước được, gây nguy hiểm cho hệ thống của bạn. Cụ thể, trong java sẽ gây ra 1 exception là NullPoiterException hoặc viết ngắn gọi là NPE.

Kotlin nhằm mục đích xóa bỏ NullPoiterException trong code của chúng ta. Ngay khi khai báo biến với Kotlin, bạn đã phải chỉ rõ biến đó có được phép Null hay không. Có 2 trường hợp được phép đó là : không thể Null và có thể Null

  • Khai báo 1 biến cho phép Null
var b: String? = "abc" // có thêm dấu ? sau kiểu của biến
b = null // compilation ok
val l = b.length // not safe
  • Khai báo 1 biến không được phép Null
var a: String = "abc"
a = null // compilation error
val l = a.length // safe

Chúng ta có thể thấy Kotlin đã khắc phục được expcetion NPE trong Java. Các biến cho phép Null hay không được phép Null đã được xác định ngay trong quá trình khai báo biến, các IDE sẽ giúp chúng ta phát hiện ra lỗi ngay khi compile. Việc phát hiện ra lỗi sớm khi compile sẽ tốt hơn so với khi runtime. Nó giúp hệ thống của chúng ta an toàn hơn.

4.3. String template

String trong kotlin có thể chứa các biểu thức template, tức là những kết quả trả về hoặc biến có thể được nối vào trong 1 String. Một biểu thức template bắt đầu với ($) và tên :

val apples = 4
valbananas = 3
println(“I have $apples apples.”)
println(“I have $apples apples and ” + (apples + bananas) + “ fruits.”)

println(“I have $apples apples and ${apples + bananas} “ fruits.”)

4.4. Kế thừa và Override

  • Mặc định class trong Kotlin đều là final (tức là không được phép kế thừa)
open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
   override fun v() {}
}
  • Trong class final (tức là không có từ khóa “open”) thì việc khai báo các hàm, thuộc tính open bị cấm
  • Ở 1 lớp con khác, hàm được đánh dấu là override thì chính nó là open (lại được kế thừa từ lớp khác), nếu muốn chống override thì lại sử dụng từ khóa final
open class AnotherDerived() : Base() {
    final override fun v() {}
}
  • Trong interface, các member mặc định là “open”
interface B {
    fun f() { print("B") } // interface members are 'open' by default
    fun b() { print("b") }
}
  • Kotlin implement interface :
class C() : A(), B {
     // The compiler requires f() to be overridden:
     override fun f() {
	super<A>.f() // call to A.f()
	super<B>.f() // call to B.f()
     }
}

4.5. Chỉ định truy cập (Visibility Modifiers)

  • Có 4 loại Visivility Modifiers trong Kotlin : private, protected, internal, và public
  • Nếu không chỉ rõ thì mặc định là public
  • Các chỉ định truy cập : private, protected và public giống cách sử dụng trọng java
  • Riêng internal ta có thể sử dụng trong cùng module

4.6. Truyền tham số trong hàm

  • Kotlin cho phép thay đổi vị trí tham số trong hàm
fun main(args : Array<String>) { 
    greet(firstName = "Frasensco", lastName = "Merini") 
    greet(lastName = "John", firstName = "Stamos") 
    greet("Borat", "Ismail") 
    greet("Crystal", lastName = "Stamos") 
    call("Xavier", age = 20, location = "Portugal") 
} 

fun greet(firstName : String, lastName : String){
    println("Good morning $firstName $lastName") 
} 

fun call(name : String, location : String, age : Int){ 
    println("Call $name who lives at $location and he is $age old") 
}

Out put :

Good morning Frasensco Merini
Good morning Stamos John
Good morning Borat Ismail
Good morning Crystal Stamos
Call Xavier who lives at Portugal and he is 20 old

Cùng đón xem phần tiếp theo trong bài viết tháng sau nhé