Hướng dẫn Scala

⚡ Tóm tắt thông minh

Hướng dẫn Scala giới thiệu một ngôn ngữ lập trình dựa trên JVM, kiểu tĩnh, kết hợp lập trình hướng đối tượng và lập trình chức năng. Hướng dẫn này bao gồm cài đặt, cú pháp, các tính năng cốt lõi và các framework giúp Scala trở nên lý tưởng để xây dựng các ứng dụng hiện đại, song song, có khả năng mở rộng và ngắn gọn.

  • 🔘 Mô hình lai: Scala kết hợp lập trình hướng đối tượng và lập trình chức năng trên JVM, cho phép các nhà phát triển kết hợp tính bất biến, các hàm hạng nhất và hệ thống phân cấp lớp truyền thống.
  • ☑️ Cú pháp ngắn gọn: Suy luận kiểu dữ liệu, hàm ẩn danh và khớp mẫu giúp giảm thiểu mã lặp lại so với các phương pháp khác. Java trong khi giữping Mã nguồn dễ hiểu và dễ đọc.
  • Thiết lập với IntelliJ: Cài đặt IDE phiên bản Community Edition, thêm plugin Scala và tạo một Object kế thừa từ App để chạy chương trình Hello World đầu tiên.
  • 🧪 Các khối cấu tạo chức năng: Việc đánh giá lười biếng, currying, hàm bậc cao và tính bất biến thông qua val hỗ trợ mã sạch và dễ dự đoán.
  • 🛠️ Tính đồng thời và các khung lập trình: Các diễn viên Akka, Futures, Play, Lift và Spark Scala là một lựa chọn mạnh mẽ cho các hệ thống phân tán, ứng dụng web và kỹ thuật dữ liệu.

Hướng dẫn Scala

Scala là gì?

Scala Scala là một ngôn ngữ lập trình kiểu tĩnh kết hợp lập trình hướng đối tượng và lập trình chức năng để cải thiện khả năng mở rộng của các ứng dụng. Scala chủ yếu chạy trên nền tảng JVM, và các nhà phát triển cũng có thể sử dụng nó để viết phần mềm cho các nền tảng gốc thông qua Scala-Native, hoặc cho trình duyệt thông qua ScalaJs và các thư viện tương ứng. JavaScript thời gian chạy.

Scala là một ngôn ngữ có khả năng mở rộng, được sử dụng để xây dựng phần mềm cho nhiều nền tảng, đúng như tên gọi của nó. Ngôn ngữ này được thiết kế để giải quyết một số vấn đề rườm rà thường gặp trong các ngôn ngữ lập trình khác. Java trong khi vẫn giữ được tính ngắn gọn. Martin Odersky đã thiết kế Scala, và phiên bản phát hành công khai đầu tiên xuất hiện vào năm 2004.

Tại sao nên học Scala

Dưới đây là những lý do chính để học ngôn ngữ lập trình Scala:

  • Scala rất dễ học đối với các lập trình viên hướng đối tượng và Java Nó được các nhà phát triển sử dụng rộng rãi và đã trở thành một trong những ngôn ngữ lập trình phổ biến trong những năm gần đây.
  • Scala cung cấp các hàm hạng nhất cho người dùng.
  • Scala có thể được thực thi trên JVM, mở đường cho khả năng tương tác với các ngôn ngữ khác.
  • Nó được thiết kế cho các ứng dụng đồng thời, phân tán và có khả năng phục hồi cao dựa trên thông điệp, điều này khiến nó trở thành một trong những ngôn ngữ được yêu cầu nhiều nhất trong thập kỷ này.
  • Đây là một ngôn ngữ ngắn gọn, mạnh mẽ, có thể nhanh chóng phát triển theo nhu cầu của người dùng.
  • Nó là ngôn ngữ lập trình hướng đối tượng và bao gồm nhiều tính năng lập trình chức năng, mang lại cho các nhà phát triển rất nhiều sự linh hoạt trong cách họ viết mã.
  • Scala cung cấp Duck Typing thông qua các loại hình cấu trúc.
  • Nó có ít đoạn văn mẫu hơn so với Java.
  • Các framework Lift và Play, được viết bằng ngôn ngữ Scala, tiếp tục phát triển và ngày càng trở nên phổ biến.

Cách cài đặt Scala

Để bắt đầu viết chương trình Scala, bạn cần cài đặt ngôn ngữ này trên máy tính của mình. Để làm điều đó, hãy truy cập trang web chính thức tại địa chỉ sau: https://www.scala-lang.org/download/ Để tải xuống phiên bản Scala mới nhất.

Sau khi nhấp vào liên kết, bạn sẽ thấy hai tùy chọn để cài đặt Scala. Trong hướng dẫn Scala này, chúng ta sẽ sử dụng tùy chọn... IntelliJ IDEA, cung cấp khả năng hỗ trợ Scala tuyệt vời ngay từ đầu.

Cách cài đặt Scala

Khi truy cập vào liên kết tải xuống, bạn sẽ thấy hai phiên bản của IDE IntelliJ.

Trong hướng dẫn Scala này, chúng ta sẽ tải xuống phiên bản Community Edition, phiên bản này miễn phí và bao gồm mọi thứ bạn cần để viết chương trình Scala.

Trang tải xuống IntelliJ Community Edition

Bước 1) Chọn phiên bản Cộng đồng.
Trên trang đó, hãy nhấp vào menu thả xuống "Phiên bản Cộng đồng".

Nó cung cấp tùy chọn tải xuống IDE IntelliJ cùng với JBR, bao gồm cả trình biên dịch JDK (Java Bộ công cụ phát triển) như OpenJDK mà Scala cần để biên dịch và chạy mã.

Tải xuống IntelliJ với JBR

Bước 2) Tiến hành cài đặt.
Sau khi tải xuống IntelliJ, hãy nhấp đúp vào trình cài đặt và làm theo hướng dẫn trên màn hình.

Trình hướng dẫn cài đặt IntelliJ

Bước 3) Chọn một địa điểm.
Chọn vị trí để cài đặt IDE.

Chọn thư mục cài đặt

Nếu bạn không tải xuống gói cài đặt kèm JDK, trình cài đặt vẫn sẽ nhắc bạn thêm JDK thông qua một hộp kiểm trong quá trình thiết lập.

Chọn hộp kiểm JDK trong quá trình cài đặt

Bước 4) Bấm tiếp.
Giữ nguyên các thiết lập mặc định khác và nhấn Tiếp theo.

Tùy chọn mặc định của trình cài đặt

Chương trình Scala Hello World

Bước 5) Nhấp vào biểu tượng khởi động.
Sau khi quá trình cài đặt hoàn tất, hãy chạy IDE IntelliJ bằng cách nhấp vào biểu tượng khởi động của nó trong menu Bắt đầu giống như một ứng dụng thông thường.

Màn hình chào mừng của IntelliJ

Bạn vẫn cần thêm plugin Scala vào IntelliJ. Nhấp vào menu thả xuống trong menu cấu hình ở góc dưới bên phải màn hình và chọn tùy chọn Plugin.

Cấu hình menu cho plugin

Chợ plugin IntelliJ

Trên tab Marketplace, tìm kiếm Scala. Plugin này sẽ xuất hiện ở vị trí đầu tiên trong kết quả tìm kiếm dưới thẻ Languages.

Bước 6) Cài đặt plugin.
Nhấp vào Cài đặt để bắt đầu tải xuống plugin Scala.

Cài đặt plugin Scala

Bước 7) Khởi động lại IDE.
Sau khi quá trình tải xuống hoàn tất, bạn sẽ được nhắc khởi động lại IDE để plugin đã cài đặt có thể bắt đầu hoạt động.

Khởi động lại IntelliJ theo hướng dẫn.

Sau khi khởi động lại, bạn sẽ quay lại trang giống như trước, nhưng giờ đây plugin Scala đã được cài đặt và sẵn sàng sử dụng.

Bước 8) Chọn Tạo dự án, thao tác này sẽ dẫn đến trang nơi bạn có thể chọn ngôn ngữ cho dự án.

Tạo dự án mới trong IntelliJ

Bước 9) Chọn Scala bằng cách chọn hộp kiểm Scala và nhấn Tiếp theo.

Chọn ngôn ngữ Scala

Bước 10) Chọn vị trí để lưu tệp dự án và đặt tên cho dự án.

Đặt tên và định vị dự án

Nếu thư mục không tồn tại, IntelliJ sẽ yêu cầu quyền tạo thư mục. Chấp nhận và nhấp vào Hoàn tất. Sau đó, bạn sẽ được chuyển đến dự án Scala của mình, hiện tại dự án này chưa chứa bất kỳ mã Scala nào.

Việc tải chỉ mục mất một chút thời gian, vì vậy đừng lo lắng nếu bạn không thể tương tác với IDE trong khi thanh tiến trình hiển thị ở phía dưới. IDE đang tải các tệp cần thiết để chạy Scala và cung cấp tính năng tự động hoàn thành.

Bước 11) Nhấp vào tab Dự án ở bên trái của IDE và mở rộng nó để xem nội dung của dự án.

Mở rộng tab dự án

Ở giai đoạn này, dự án còn trống và chỉ chứa thư mục .idea cùng tệp hello-world.iml được tạo bởi IDE. Điểm đáng chú ý là thư mục src, nơi chứa mã nguồn của dự án. Đây là nơi bạn tạo tệp Scala đầu tiên của mình.

Bước 12) Nhấp chuột phải vào thư mục src để mở menu và tạo tệp Scala mới.

Tạo một tệp Scala mới

Chọn một tên cho tệp. Đối với hướng dẫn Scala này, hãy sử dụng xin chàoSau đó, chọn Object từ menu thả xuống cho kiểu nội dung của tệp Scala.

Chọn loại đối tượng

Sau khi thực hiện điều này, bạn sẽ có một tệp Scala chứa một đối tượng singleton mà bạn sẽ sử dụng để chạy mã.

Đối tượng Singleton được tạo

Giờ bạn đã có một file Scala với đối tượng Hello, hãy viết chương trình đầu tiên bằng cách kế thừa đối tượng bạn vừa tạo bằng từ khóa App.

Việc mở rộng đối tượng bằng từ khóa `App` cho trình biên dịch biết đoạn mã nào cần chạy khi chương trình bắt đầu. Ngay sau khi mở rộng `App`, một mũi tên màu xanh lá cây sẽ xuất hiện ở phía bên trái, cho biết chương trình hiện đã có thể chạy được.

Chạy lệnh Arrow trong IntelliJ

Chạy tùy chọn Hello

Bên trong đối tượng Hello, hãy viết hàm println() để in văn bản ra màn hình console. Chạy chương trình bằng cách nhấp vào mũi tên màu xanh lá cây.

Nhấp vào mũi tên sẽ hiển thị tùy chọn Chạy Hello. Chọn tùy chọn này sẽ biên dịch mã, và sau vài giây, kết quả chương trình sẽ xuất hiện trong cửa sổ dòng lệnh IntelliJ.

Kết quả "Hello World" hiển thị trên console

Bạn đã cài đặt Scala thành công và chạy chương trình đầu tiên của mình.

Bạn có thể làm gì với Scala

Scala được sử dụng rộng rãi trong nhiều lĩnh vực nhờ tính linh hoạt và khả năng tương tác với JVM. Các trường hợp sử dụng phổ biến bao gồm:

  • Phát triển giao diện người dùng web bằng ScalaJS.
  • Phát triển ứng dụng di động cho Android và iOS với Scala Native.
  • Các thư viện phía máy chủ như HTTP4S, Akka-Http và Play Framework.
  • Các ứng dụng Internet vạn vật (IoT).
  • Sự phát triển trò chơi.
  • Xử lý ngôn ngữ tự nhiên bằng bộ thư viện ScalaNLP.
  • Thực hành đồng thời các kỹ thuật nâng cao như lập trình hàm và lập trình hướng đối tượng.
  • Các ứng dụng giao tiếp đồng thời cao sử dụng actor, một thư viện dành cho JVM lấy cảm hứng từ Erlang.
  • Học máy với các thư viện như Figaro cho lập trình xác suất và Apache. Spark Dùng cho xử lý dữ liệu quy mô lớn.

Hàm ẩn danh

Ngôn ngữ Scala hỗ trợ các hàm ẩn danh, còn được gọi là chữ chức năngVì Scala là một ngôn ngữ lập trình hướng chức năng, các nhà phát triển thường chia nhỏ các vấn đề lớn thành nhiều nhiệm vụ nhỏ và tạo ra nhiều hàm. Để đơn giản hóa việc này, Scala cho phép các hàm được khai báo. khởi tạo mà không có tênBạn có thể gán chúng trực tiếp cho các biến hoặc cho các định nghĩa bằng cách sử dụng... defnhư được minh họa trong ví dụ Scala sau:

val multiplyByTwo = (n:Int) => n * 2
def multiplyByThree = (n:Int) => n * 3

Sau đó, bạn có thể sử dụng chúng như các hàm thông thường bằng cách truyền tham số:

multiplyByTwo(3)
//6

multiplyByThree(4)
//12

Những phương pháp này rất hữu ích khi bạn muốn có mã nguồn sạch sẽ và ngắn gọn. Hàm ẩn danh rất hữu ích khi định nghĩa các phương thức nhỏ và không yêu cầu nhiều mã trong phần thân của chúng. Chúng rất đơn giản và không cần bất kỳ thủ tục phức tạp nào để tạo ra.

Các phương pháp này không chỉ giới hạn ở các hàm có đối số mà còn có thể được sử dụng để khởi tạo các phương thức không có đối số.

val sayHello = () => { println("hello") }

Hầu hết các hàm ẩn danh này được sử dụng trong các phần khác của mã nguồn, nơi bạn cần một hàm nhanh chóng có sẵn. Vì lý do này, chúng cũng được gọi là hàm ẩn danh. hàm nội tuyếnViệc sử dụng các hàm ẩn danh là một mô hình phổ biến xuất hiện xuyên suốt thư viện collections để thực hiện các thao tác nhanh chóng trên một collection.

Ví dụ, phương thức filter sử dụng một hàm nội tuyến để tạo một tập hợp khác chỉ chứa các phần tử đáp ứng các tiêu chí được định nghĩa trong hàm ẩn danh.

val myList = List(1,2,3,4,5,6,7)

val myEvenList = myList.filter((n: Int) => n % 2 == 0)
//List(2,4,6)

val myOddList = myList.filter((n:Int) => n % 2 != 0)
//List(1,3,5,7)

Tại đây, các hàm ẩn danh kiểm tra xem giá trị trong danh sách là số lẻ hay số chẵn và trả về phần tử phù hợp.

//the one checking that the value is even
(n: Int) => n % 2 == 0

//the one checking that the value is odd
(n:Int) => n % 2 != 0

Trong Scala, cũng có thể sử dụng ký tự đại diện khi tham số của hàm ẩn danh không được đặt tên. Ví dụ:

var timesTwo = (_:Int) * 2

timesTwo(5)
//10

Trong trường hợp này, bạn không cần đặt tên cho tham số. Dấu gạch dưới được sử dụng để biểu thị tham số đó.

Đánh giá lười biếng

Hầu hết các ngôn ngữ đều đánh giá tuần tự các biến và tham số hàm, lần lượt từng cái một. Trong Scala, từ khóa lazy Giúp xử lý các giá trị mà bạn không muốn đánh giá cho đến khi chúng được tham chiếu.

Biến được đánh dấu là lazy không được đánh giá tại nơi nó được định nghĩa, điều này thường được gọi là đánh giá tức thời (eager evaluation). Nó chỉ được đánh giá khi được tham chiếu sau đó trong mã.

Điều này có thể hữu ích khi việc đánh giá một giá trị đòi hỏi tính toán tốn kém. Nếu giá trị đó không phải lúc nào cũng cần thiết, bạn sẽ tránh được việc thực hiện một phép tính tốn kém có thể làm chậm phần mềm bằng cách làm cho biến đó trở nên "lười biếng" (lazy).

lazy val myExpensiveValue = expensiveComputation

def runMethod() = {
    if(settings == true) {
        use(myExpensiveValue)
    } else {
        use(otherValue)
    }
}

Đây không phải là trường hợp sử dụng duy nhất của biến lười biếng. Chúng cũng giúp xử lý các phụ thuộc vòng tròn trong mã.

Nếu cờ cài đặt là false, bạn không cần sử dụng myExpensiveValue, giúp tiết kiệm chi phí tính toán. Điều này giúp đảm bảo người dùng có trải nghiệm mượt mà vì tài nguyên không bị lãng phí vào các giá trị không bao giờ được đọc.

Tính lười biếng cũng hữu ích với các đối số hàm, trong đó các đối số chỉ được sử dụng khi chúng được tham chiếu bên trong hàm. Khái niệm này được gọi là tham số truyền theo tên (Call-by-name parameters).

def sometimesUsedString(someValue:String, defaultValue: => String) = {
 if(someValue != null) {
   use(defaultValue)
 } else {
   use(someValue)
   }
 }

Nhiều ngôn ngữ lập trình sử dụng phương pháp truyền tham số theo giá trị (call-by-value). Tham số được truyền theo tên (call-by-name) chỉ được đánh giá khi cần thiết bên trong thân hàm. Sau khi giá trị được đánh giá, nó được lưu trữ và có thể được sử dụng lại sau này mà không cần đánh giá lại, một khái niệm được gọi là ghi nhớ (memoization).

Kiểu suy luận

Trong Scala, bạn không cần phải khai báo kiểu dữ liệu cho mọi biến mình tạo ra vì trình biên dịch Scala có thể suy luận kiểu dữ liệu từ phía bên phải của biểu thức. Điều này giúp mã của bạn ngắn gọn hơn và tránh phải viết những đoạn mã lặp đi lặp lại khi kiểu dữ liệu mong muốn đã rõ ràng.

var first:String = "Hello, "
var second:String = "World"
var third = first + second
//the compiler infers that third is of type String

Hàm bậc cao

Hàm bậc cao là hàm có thể nhận các hàm khác làm đối số và trả về một hàm làm kiểu trả về. Trong Scala, các hàm được coi là các đối tượng hạng nhất. Việc sử dụng hàm theo cách này cho phép bạn rất linh hoạt trong việc xây dựng các loại chương trình. Bạn có thể tạo các hàm một cách động và truyền chức năng một cách động cho các hàm khác.

def doMathToInt(n:Int, myMathFunction:Int=>Int): Int = {
    myMathFunction(n)
}

Trong hàm trên, bạn truyền vào một tham số Int và một hàm nhận vào một Int và trả về một IntBạn có thể truyền vào bất kỳ hàm nào có chữ ký đó. Chữ ký ở đây được hiểu là đầu vào và đầu ra của một hàm. Chữ ký của Int => Int Điều này có nghĩa là một hàm nhận một số nguyên làm đầu vào và trả về một số nguyên làm đầu ra.

Chữ ký của () => Int Điều này có nghĩa là một hàm không nhận đầu vào nào và trả về một số nguyên (Int) làm đầu ra. Một ví dụ về hàm như vậy là hàm tạo ra một số nguyên ngẫu nhiên.

def generateRandomInt() = {
 return scala.util.Random.nextInt()
}

Hàm trên có chữ ký. () => Int.

Một hàm cũng có thể có chữ ký. () => UnitĐiều này có nghĩa là hàm không nhận tham số đầu vào nào và không trả về kiểu dữ liệu nào. Thay vào đó, hàm có thể thay đổi một trạng thái nào đó hoặc thực hiện một hành động đã được xác định trước.

Những phương pháp kiểu này không được khuyến khích vì chúng có thể hoạt động như một hộp đen, ảnh hưởng đến hệ thống theo những cách không thể đoán trước. Chúng cũng khó kiểm thử hơn. Việc có các kiểu đầu vào và đầu ra rõ ràng cho phép bạn hiểu được chức năng của mình hoạt động như thế nào.

Hàm bậc cao cũng có thể trả về một hàm. Ví dụ, bạn có thể tạo một phương thức trả về một hàm lũy thừa, một hàm nhận vào một số và áp dụng lũy ​​thừa cho số đó.

def powerByFunction(n:Int): Int=>Int = {
  return (x:Int) => scala.math.pow(x,n).toInt
}

Hàm trên nhận một tham số kiểu Int. Kiểu trả về của nó là một hàm ẩn danh cũng nhận một tham số kiểu Int. x và sử dụng nó làm đối số cho hàm lũy thừa.

cà ri

Trong Scala, bạn có thể chuyển đổi một hàm nhận hai tham số thành một hàm nhận một tham số tại một thời điểm. Khi bạn truyền vào một tham số, bạn sẽ áp dụng một phần tham số đó và kết quả là một hàm nhận tham số còn lại để hoàn thành lời gọi hàm. Currying cho phép bạn xây dựng các hàm bằng cách thêm một phần các tham số.

Điều này rất hữu ích để tạo các hàm một cách động trước khi bạn có đầy đủ các đối số.

def multiplyTwoNumbers(n:Int)(m:Int): Int = {
  return n * m
}

Nếu bạn cần một hàm nhân với một số cụ thể, bạn không cần tạo thêm một phương thức nhân khác. Bạn có thể áp dụng một đối số cho hàm curried và sử dụng lại kết quả:

def multiplyTwoNumbers(n:Int)(m:Int): Int = {
  return n * m
}

var multiplyByFive = multiplyTwoNumbers(5) _

multiplyByFive(4)

//returns 20

Khớp mẫu

Scala có một cơ chế tích hợp mạnh mẽ giúp bạn kiểm tra xem một biến có đáp ứng các tiêu chí nhất định hay không, tương tự như câu lệnh switch trong lập trình. Java hoặc một chuỗi các câu lệnh if/else. Ngôn ngữ này hỗ trợ khớp mẫu, bạn có thể sử dụng nó để kiểm tra xem một biến có thuộc một kiểu cụ thể hay không. Khớp mẫu trong Scala rất mạnh mẽ và có thể phân tách các thành phần có một unapply Phương pháp để lấy trực tiếp các trường bạn quan tâm từ biến đang được so khớp.

Việc sử dụng khớp mẫu trong Scala cũng cung cấp cú pháp dễ chịu hơn so với câu lệnh switch.

myItem match {
  case true => //do something
  case false => //do something else
  case  _ => //if none of the above do this by default
}

Bạn so sánh biến số với một tập hợp các tùy chọn. Khi biến số đáp ứng các tiêu chí, biểu thức ở phía bên phải của dấu mũi tên đậm (=>) sẽ được đánh giá và trả về kết quả phù hợp.

Dấu gạch dưới bắt các trường hợp không khớp trong mã, phản ánh hành vi của trường hợp mặc định trong câu lệnh switch.

class Animal(var legs:Int, var sound:String)
class Furniture(var legs:Int, var color:Int, var woodType:String)

myItem match {
case myItem:Animal => //do something
case myItem:Furniture => //do something else
case _ => //unknown type, do something else
}

Trong đoạn mã trên, bạn có thể phát hiện loại của myItem biến và dựa trên đó, phân nhánh thành các đoạn mã cụ thể.

So khớp mẫu kiểm tra xem biến đó có khớp với từng trường hợp theo thứ tự hay không.

Dấu gạch dưới hoạt động như một ký tự giữ chỗ khớp với bất kỳ điều kiện nào mà các câu lệnh case khác không khớp. Bạn lấy một biến. myItem và gọi cho match phương pháp.

  • Kiểm tra xem myItem is true và chạy logic ở phía bên phải của mũi tên đậm “=>”.
  • Sử dụng dấu gạch dưới để khớp với bất kỳ thứ gì không khớp với bất kỳ câu lệnh điều kiện nào được định nghĩa trong mã.

Với các lớp case, bạn có thể phân rã lớp để ví dụ như...traccác trường t bên trong đối tượng.

Bằng việc sử dụng sealed Sử dụng từ khóa để định nghĩa các lớp, bạn sẽ nhận được lợi ích là trình biên dịch sẽ kiểm tra kỹ lưỡng các trường hợp bạn cố gắng khớp và cảnh báo bạn nếu bạn quên xử lý một trường hợp nào đó.

Bất biến

Trong Scala, có thể tạo ra các giá trị không thể thay đổi bởi các hàm khác bằng cách sử dụng phương thức sau: val từ khóa. Điều này được thực hiện trong Java bằng cách sử dụng final từ khóa. Trong Scala, bạn sử dụng một val khi tạo một biến thay vì var, đây là phương án thay thế cho các biến có thể thay đổi.

Một biến được định nghĩa bằng cách sử dụng val Từ khóa chỉ đọc, trong khi từ khóa được định nghĩa bằng var có thể được đọc và thay đổi sau này bởi các hàm khác hoặc bởi người dùng trong mã nguồn.

var changeableVariable = 8

changeableVariable = 10
//the compiler does not complain, and the code compiles successfully

println(changeableVariable)
//10

val myNumber = 7

myNumber = 4

//this will not compile

Đang cố gắng gán giá trị cho myNumber sau khi tuyên bố nó là một val Gây ra lỗi biên dịch: “gán lại cho val.”

Tại sao nên sử dụng tính bất biến?

Tính bất biến giúp ngăn chặn mã nguồn và các lập trình viên khác thay đổi giá trị một cách bất ngờ, dẫn đến kết quả khó lường. Nếu người sử dụng cần thay đổi một giá trị, họ có thể tạo một bản sao. Bằng cách này, các lỗi do nhiều tác nhân cùng thay đổi một biến được ngăn chặn.

Lớp và Đối tượng

Đối tượng là các thực thể trong thế giới thực, còn lớp là một khuôn mẫu định nghĩa các đối tượng. Lớp có cả trạng thái và hành vi. Trạng thái có thể là giá trị hoặc biến. Hành vi chính là các phương thức trong Scala.

Phần tiếp theo sẽ hướng dẫn cách định nghĩa một lớp, khởi tạo một thể hiện của lớp đó và sử dụng nó trong Scala.

Đây là một lớp có tên là Rectangle, lớp này có hai giá trị và hai hàm. Bạn cũng có thể sử dụng các tham số. lb Trực tiếp dưới dạng các trường trong chương trình. Bạn có một đối tượng có phương thức main và khởi tạo lớp với hai giá trị.

Ví dụ:

class Rectangle(l: Int, b: Int) {
  val length: Int = l
  val breadth: Int = b
  def getArea: Int = l * b
  override def toString = s"This is a rectangle with length $length and breadth $breadth"
}
object RectObject {
  def main(args: Array[String]) {
    val rect = new Rectangle(4, 5)
    println(rect.toString)
    println(rect.getArea)
  }
}

Theo mặc định, tất cả các trường và phương thức đều là public trong Scala. Điều cần thiết là sử dụng override bởi vì toString Nó đã được định nghĩa sẵn cho mọi đối tượng trong Scala.

di sản

Scala có nhiều kiểu kế thừa (đơn cấp, đa cấp, bội, phân cấp và lai) có nhiều điểm chung với các hình thức truyền thống được tìm thấy trong... JavaBạn có thể kế thừa cả từ lớp và từ đặc tính. Bạn kế thừa các thành viên của một lớp vào một lớp khác bằng cách sử dụng từ khóa. extendsĐiều này cho phép tái sử dụng.

Có thể kế thừa từ một lớp hoặc nhiều lớp. Cũng có thể kế thừa từ các lớp con mà bản thân chúng lại có các lớp cha, tạo ra một hệ thống phân cấp kế thừa.

Trong ví dụ Scala bên dưới, lớp cơ sở là Circlevà lớp dẫn xuất là SphereMột hình tròn có một giá trị gọi là bán kính, giá trị này được kế thừa trong lớp Sphere. Phương thức calcArea được ghi đè bằng từ khóa override.

Ví dụ:

class Circle {
  val radius = 5
  def calcArea = {
    println(radius * radius)
  }
}
class Sphere extends Circle {
 override def calcArea = {
    println(radius * radius * radius)
  }
}
  object SphereObject {
    def main(args : Array[String]) {
      new Sphere().calcArea
    }
  }

Abstracsản xuất

Trong Scala, bạn có thể tạo abstraccác phương pháp t và các trường thành viên sử dụng abstraccác lớp và đặc điểm t. Bên trong abstract lớp và đặc điểm, bạn có thể định nghĩa abstraccác trường t mà không cần triển khai chúng.

Ví dụ:

trait MakesSound {
    var nameOfSound:String
    def sound():String
}
abstract class HasLegs(var legs:Int) {
    val creatureName:String

    def printLegs():String = {
        return s"$creatureName has this number of legs: $legs"
    }
}

Các trường này được triển khai bởi các lớp mở rộng trait hoặc abs.traclớp t. Bạn có thể sử dụng các đặc tính để tạo ra contracHãy xác định những gì ứng dụng nên làm, rồi sau đó triển khai các phương thức đó.

trait DatabaseService {
    def addItemName(itemName:String)
    def removeItem(itemId:Int)
    def updateItem(itemId:Int, newItemName:String)
}

Bằng cách này, bạn có thể lên kế hoạch về giao diện của ứng dụng mà không cần phải tự triển khai các phương thức.ping Bạn hình dung ra cách các phương pháp khác nhau sẽ xuất hiện. Nó tuân theo một mô hình được gọi là lập trình để giải quyết vấn đề.tractập trung vào các ý kiến ​​hơn là vào việc thực hiện thực tế.

Một lớp học được mở đầu bằng abstract Từ khóa có thể chứa cả abstract và không tuyệt đốitraccác phương thức t. Tuy nhiên, đa kế thừa không được hỗ trợ trong abs.traccác lớp t, vì vậy bạn chỉ có thể mở rộng một abstraclớp t.

Đối tượng đơn

Singleton là một lớp chỉ được khởi tạo một lần duy nhất trong chương trình. Khái niệm này xuất phát từ một mẫu lập trình phổ biến và hữu ích được gọi là "mẫu singleton". Nó hữu ích cho việc tạo ra các thể hiện có tuổi thọ dài và được truy cập thường xuyên trong suốt chương trình, nơi trạng thái là yếu tố không thể thiếu để điều phối các sự kiện trong hệ thống. Việc tạo ra một lớp như vậy trong Scala rất dễ dàng vì Scala cung cấp một phương tiện đơn giản để tạo ra các singleton bằng cách sử dụng... object từ khóa.

object UserProfile {
    var userName = ""
    var isLoggedIn:Boolean = false
}

Sau đó, bạn có thể tham chiếu đến đối tượng này trong toàn bộ chương trình với sự đảm bảo rằng tất cả các phần của chương trình đều thấy cùng một dữ liệu vì chỉ có một thể hiện duy nhất của nó.

def getLoggedInStatus():Boolean = {
   return UserProfile.isLoggedIn
}

def changeLoggedInStatus():Boolean = {
    UserProfile.isLoggedIn = !UserProfile.isLoggedIn
    return UserProfile.isLoggedIn
}

Khái niệm về thành viên tĩnh không tồn tại trong Scala, đó là lý do tại sao bạn sử dụng các đối tượng singleton hoạt động như các thành viên tĩnh của một lớp.

Lớp ngầm

Các lớp ngầm định là một tính năng được thêm vào trong phiên bản 2.10 và chủ yếu được sử dụng để bổ sung chức năng mới cho các lớp đóng hiện có.

implicit Từ khóa phải được định nghĩa trong một lớp, đối tượng hoặc trait. Hàm tạo chính của một lớp ngầm định phải có chính xác một đối số trong danh sách tham số đầu tiên của nó. Nó cũng có thể bao gồm một danh sách tham số ngầm định bổ sung.

Trong ví dụ Scala bên dưới, chức năng mới để thay thế các nguyên âm của một chuỗi bằng ký tự * đã được thêm vào.

object StringUtil {
  implicit class StringEnhancer(str: String) {

    def replaceVowelWithStar: String = str.replaceAll("[aeiou]", "*")
  }
}

Bạn cần nhập lớp ngầm định vào lớp mà bạn đang sử dụng nó.

import StringUtil.StringEnhancer

object ImplicitEx extends App {
  val msg = "This is Guru99!"
  println(msg.replaceVowelWithStar)
}

Lập trình hướng đối tượng (OOP) so với lập trình chức năng (FP)

Trong lập trình hướng đối tượng (OOP), các chương trình được xây dựng bởi nhóm.ping Dữ liệu và các hàm hoạt động trên dữ liệu đó được chia thành các đơn vị liên kết chặt chẽ. Các đối tượng mang dữ liệu của chúng trong các trường và các phương thức hoạt động trên chúng. Trong kiểu lập trình này, phần chính...trac"Tation" chính là dữ liệu, bởi vì các phương thức được tạo ra đều nhằm mục đích hoạt động trên dữ liệu đó.

Lập trình chức năngNgược lại, phương pháp này tách biệt dữ liệu và các hàm hoạt động trên dữ liệu đó. Điều này cho phép các nhà phát triển coi các hàm như là các thành phần tuyệt đối.traclà động lực và yếu tố thúc đẩy khi lập trình mô hình.

Scala cho phép lập trình hàm bằng cách coi các hàm như những đối tượng hạng nhất, cho phép chúng được truyền làm giá trị cho các hàm khác và cũng được trả về làm giá trị. Sự kết hợp của hai mô hình này đã làm cho Scala trở thành lựa chọn tuyệt vời để xây dựng phần mềm phức tạp trong các ngành như khoa học dữ liệu.

Các framework quan trọng trên Scala

Dưới đây là một số framework quan trọng dành cho Scala:

  • Play là một khung ứng dụng web nguồn mở sử dụng Kiến trúc MVCĐược phát hành vào năm 2007 và hiện được cấp phép bởi Apache, nó đã trở thành một trong những framework phổ biến nhất trên GitHub vào năm 2013. Các công ty như LinkedIn, WalmartSamsung và Eero đều sử dụng khung phần mềm này.
  • thang máy Lift là một framework web miễn phí khác được viết bằng Scala, ra mắt năm 2007. Foursquare sử dụng framework Lift. Đây là một framework hiệu năng cao và xây dựng ứng dụng rất nhanh.
  • mẫu Anh Cung cấp bộ công cụ để xây dựng các ứng dụng hướng thông điệp có tính đồng thời cao, phân tán và bền vững trên JVM.
  • Mèo là một thư viện cung cấp abstraccác phương án lập trình hàm.
  • Spark Đây là một công cụ phân tích thống nhất用于 xử lý dữ liệu quy mô lớn, được sử dụng rộng rãi trong các quy trình làm việc về dữ liệu lớn và học máy.

Hỗ trợ đồng thời

  • Các giá trị trong Scala mặc định là bất biến, điều này làm cho nó rất thích ứng với môi trường xử lý đồng thời.
  • Scala có nhiều tính năng khiến nó trở nên lý tưởng cho các ứng dụng xử lý đồng thời.
  • Futures và Promises giúp xử lý dữ liệu không đồng bộ dễ dàng hơn, do đó hỗ trợ tính song song.
  • Akka là một bộ công cụ sử dụng mô hình đồng thời Actor. Các Actor sẽ hành động khi nhận được thông báo.
  • Đồng thời sử dụng các luồng từ Java Tính năng này cũng được hỗ trợ trong Scala.
  • Xử lý luồng dữ liệu là một tính năng tuyệt vời khác cho phép xử lý dữ liệu liên tục, theo thời gian thực.

Scala có một số thư viện xử lý đồng thời tốt nhất trong Java hệ sinh thái:

  • Native Java chủ đề.
  • Các sợi quang từ các thư viện như Vertx.
  • ZIO là một thư viện chứa các hàm cơ bản giúp xử lý tính toán đồng thời và bất đồng bộ.
  • Bộ nhớ giao dịch phần mềm (STM) dành cho các giao dịch.
  • Future, một tính năng được tích hợp sẵn trong ngôn ngữ Scala.

Java so với Scala

Đây là chính Khác biệt giữa Java và Scala.

Scala Java
Ngắn gọn và súc tích hơn. Các đoạn mã có kích thước tương đối lớn hơn.
Được thiết kế và phát triển theo cả hướng đối tượng và hướng chức năng. Hỗ trợ nhiều tính năng lập trình chức năng như xử lý song song và tính bất biến. Ban đầu được phát triển như một ngôn ngữ lập trình hướng đối tượng và bắt đầu hỗ trợ các tính năng lập trình chức năng trong các phiên bản gần đây. Tuy nhiên, nó vẫn chưa mạnh bằng Scala về lập trình chức năng.
Sử dụng mô hình actor để hỗ trợ xử lý đồng thời. Sử dụng mô hình dựa trên luồng thông thường để chạy đồng thời.
Hỗ trợ các framework như Play và Lift. Hỗ trợ Spring, Grails và nhiều framework khác.
Hỗ trợ đánh giá lười biếng. Không hỗ trợ đánh giá lười biếng một cách tự nhiên.
Không có thành viên nào đứng yên. Chứa các thành viên tĩnh.
Hỗ trợ quá tải toán tử. Không hỗ trợ nạp chồng toán tử.
Quá trình biên dịch mã nguồn diễn ra tương đối chậm. Việc biên dịch mã nguồn nhanh hơn so với Scala.
Các đặc điểm hoạt động như Java 8 giao diện. Java 8 giao diện cố gắng thu hẹp khoảng cách giữa các lớp và giao diện.
Việc viết lại mã đôi khi là cần thiết khi nâng cấp phiên bản. Việc viết lại nội dung giữa các phiên bản thường không bắt buộc.
Tính an toàn kiểu dữ liệu mang lại độ tin cậy cao cho mã nguồn nhưng không đảm bảo tuyệt đối không có lỗi. Tĩnh điện mạnhping Giúp giảm thiểu nhiều lỗi trong quá trình thực thi.
Có một số hạn chế về khả năng tương thích ngược giữa các phiên bản chính. Khả năng tương thích ngược mạnh mẽ trong thời gian dài.
OperaTor được coi như các lệnh gọi phương thức. OperaTor là cú pháp đặc biệt và không phải là các lệnh gọi phương thức.
Hỗ trợ kế thừa đa cấp bằng cách sử dụng các đặc tính. Không hỗ trợ kế thừa đa lớp bằng cách sử dụng các lớp; thay vào đó sử dụng giao diện.
Code được viết dưới dạng ngắn gọn. Code được viết dưới dạng dài dòng hơn.
Scala không chứa từ khóa tĩnh. Java chứa từ khóa tĩnh.

Câu Hỏi Thường Gặp

Scala có đường cong học tập dốc hơn so với... Java Bởi vì nó kết hợp phong cách lập trình hướng đối tượng và lập trình chức năng. Tuy nhiên, các nhà phát triển với Java Người có kinh nghiệm thường nhanh chóng nắm bắt được những kiến ​​thức cơ bản. Thực hành với các dự án nhỏ và Scala REPL sẽ giúp đẩy nhanh quá trình học tập.

Đúng vậy. Scala vẫn tiếp tục là ngôn ngữ lập trình hỗ trợ các hệ thống quy mô lớn tại các công ty sử dụng Akka. Sparkvà Kafka. Nhu cầu vẫn mạnh mẽ trong lĩnh vực kỹ thuật dữ liệu, công nghệ tài chính và hệ thống phân tán, nơi hiệu năng của JVM và lập trình hàm rất quan trọng.

Đúng vậy. Các trợ lý lập trình AI hiện đại hiểu cú pháp Scala, hệ thống kiểu dữ liệu và các framework như Akka. SparkChúng giúp tạo ra mã mẫu, đề xuất các mẫu lập trình hàm, giải thích lỗi trình biên dịch và tái cấu trúc mã, đẩy nhanh quá trình phát triển cho cả người mới bắt đầu và chuyên gia.

Scala điều khiển Apache SparkScala là ngôn ngữ lập trình hàng đầu cho việc xử lý dữ liệu quy mô lớn trong các quy trình AI. Các thư viện như Breeze, Smile và Figaro hỗ trợ tính toán số học, học máy và mô hình hóa xác suất, biến Scala trở thành lựa chọn mạnh mẽ cho khoa học dữ liệu sản xuất.

Biến `val` tạo ra một liên kết bất biến được đánh giá ngay lập tức. Biến `var` tạo ra một liên kết có thể thay đổi, có thể được gán lại giá trị. Biến `lazy val` trì hoãn việc đánh giá cho đến khi giá trị được truy cập lần đầu tiên, sau đó lưu trữ kết quả để sử dụng cho các lần đọc tiếp theo.

Tóm tắt bài viết này với: