Hướng dẫn Scala
Tóm tắt hướng dẫn Scala
Hướng dẫn scala này bao gồm tất cả các khía cạnh và chủ đề của scala. Bạn sẽ tìm hiểu tất cả các nguyên tắc cơ bản từ đầu như scala là gì, Quy trình cài đặt scala, chương trình Scala, Hàm Scala, Đánh giá lười biếng, Giao diện loại, lớp và đối tượng, Kế thừa, Trừu tượng, Java và sự khác biệt scala, v.v.
Scala là gì?
Scala là ngôn ngữ lập trình kiểu tĩnh kết hợp cả lập trình chức năng và hướng đối tượng để tăng khả năng mở rộng của ứng dụng. Scala chủ yếu chạy trên nền tảng JVM và nó cũng có thể được sử dụng để viết phần mềm cho các nền tảng gốc bằng Scala-Native và JavaScript thời gian chạy thông qua ScalaJs.
Scala là Ngôn ngữ có khả năng mở rộng được sử dụng để viết Phần mềm cho nhiều nền tảng. Do đó, nó có tên là Scala. Ngôn ngữ này nhằm giải quyết các vấn đề của Java đồng thời ngắn gọn hơn. Ban đầu được thiết kế bởi Martin Odersky, nó được phát hành vào năm 2003.
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, Java nhà phát triển. Nó đang trở thành một trong những ngôn ngữ phổ biến trong những năm gần đây.
- Scala cung cấp các chức năng hạng nhất cho người dùng
- Scala có thể được thực thi trên JVM, do đó 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à điều khiển thông điệp linh hoạt. Đây là một trong những ngôn ngữ đòi hỏi khắt khe nhất trong thập kỷ này.
- Đó là ngôn ngữ ngắn gọn, mạnh mẽ và có thể nhanh chóng phát triển theo nhu cầu của người dùng.
- Nó hướng đối tượng và có nhiều tính năng lập trình chức năng mang lại sự linh hoạt cho các nhà phát triển để viết mã theo cách họ muốn.
- Scala cung cấp nhiều loại Vịt
- Nó có ít bản soạn sẵn hơn nếu bạn đến từ Java
- Các framework Lift and Play được viết bằng Scala đang trong đường cong tăng trưởng.
Cách cài đặt Scala
Để bắt đầu viết chương trình Scala, bạn cần cài đặt nó trên máy tính của mình. Để thực hiện việc này, bạn sẽ cần phải truy cập trang web của họ https://www.scala-lang.org/download/ để tải xuống phiên bản mới nhất của Scala.
Theo liên kết, chúng ta được dẫn đến hai tùy chọn mà chúng ta có thể chọn để cài đặt Scala trên máy của mình. Đối với hướng dẫn Scala này, chúng ta sẽ tải xuống IntelliJ IDEA.
Khi truy cập liên kết tải xuống, bạn sẽ tìm thấy hai phiên bản của IntelliJ IDE.
Đối với hướng dẫn Scala này, chúng tôi sẽ tải xuống Phiên bản cộng đồng, phiên bản này miễn phí và đi kèm với tất cả những gì bạn cần để viết chương trình Scala.
Bước 1) Chọn phiên bản cộng đồng
Trên trang, nhấp vào menu thả xuống trên Phiên bản cộng đồng.
Nó cung cấp cho chúng tôi tùy chọn tải xuống IntelliJ IDE cùng với JBR có chứa triển khai JDK(Java Bộ công cụ phát triển) OpenJDK mà Scala cần biên dịch và chạy mã.
Bước 2) Chạy cài đặt
Sau khi tải xuống IntelliJ, hãy nhấp đúp vào nó để chạy trình hướng dẫn cài đặt và làm theo hộp thoại.
Bước 3) Chọn một địa điểm
Chọn vị trí để cài đặt IDE.
Nếu chẳng may bạn không tải xuống phiên bản có JDK, chúng ta vẫn nhận được lời nhắc yêu cầu bạn kiểm tra để tải xuống bằng cách chọn hộp kiểm.
Bước 4) Bấm vào tiếp theo
Để nguyên các giá trị mặc định khác và nhấp vào tiếp theo.
Bước 5) Bấm 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 IntelliJ IDE bằng cách nhấp vào biểu tượng khởi động của nó trong menu khởi động giống như một ứng dụng thông thường.
Bạn vẫn cần thực hiện thêm bước thêm plugin Scala vào IntelliJ; bạn làm như vậy bằng cách nhấp vào menu thả xuống trên menu cấu hình nằm ở phía dưới bên phải màn hình và chọn tùy chọn plugin.
Trên tab Marketplace, tìm kiếm Scala sẽ hiển thị plugin dưới dạng kết quả đầu tiên trong thẻ Ngôn ngữ.
Bước 6) Cài đặt plugin
Nhấp vào cài đặt, thao tác này sẽ dẫn plugin bắt đầu tải xuống.
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.
Sau khi khởi động lại, bạn sẽ thấy mình ở cùng trang như trước đây khi chúng tôi chạy IDE, nhưng lần này chúng tôi đã cài đặt plugin Scala.
Chương trình Scala Hello World
Bước 1) Chọn tùy chọn Tạo dự án, tùy chọn này sẽ dẫn chúng ta đến một trang nơi chúng ta có thể chọn loại ngôn ngữ mà dự án của chúng ta sẽ sử dụng.
Bước 2) chọn Scala bằng cách chọn hộp kiểm Scala và nhấp vào tiếp theo.
Bước 3) Chọn một vị trí để lưu tệp dự án của chúng tôi và đặt tên cho dự án của chúng tôi.
Nếu thư mục không tồn tại, IntelliJ sẽ nhắc chúng tôi xin phép chúng tôi để tạo thư mục. Chấp nhận và nhấp vào kết thúc. Bạn sẽ được đưa đến dự án Scala của mình, dự án này hiện chưa có bất kỳ mã Scala nào.
Sẽ mất một chút thời gian để tải một số chỉ mục, vì vậy đừng lo lắng nếu bạn không thể làm bất cứ điều gì ngay lập tức trong khi có thanh tiến trình ở cuối IDE, điều đó đơn giản có nghĩa là IDE của bạn đang tải một số tệp cần thiết để chạy Scala và trợ giúp về tính năng tự động hoàn thành của IDE.
Bước 4) Tiếp theo, chúng ta sẽ nhấp vào tab dự án ở bên trái IDE và mở rộng để có thể xem nội dung dự án của mình.
Hiện tại dự án trống và chỉ chứa thư mục .idea và tệp hello-world.iml do IDE tạo. Điểm quan tâm của chúng tôi là thư mục src. Src là nơi chúng ta lưu trữ mã nguồn cho dự án của mình. Đó là nơi chúng ta sẽ tạo tệp Scala đầu tiên.
Bước 5) Nhấp chuột phải vào src để mở menu tạo tệp Scala mới.
Sau đó, chúng ta sẽ tạo tên cho tệp, trong hướng dẫn Scala này, chúng ta sẽ sử dụng hello và sau đó chọn từ danh sách thả xuống nội dung cần đặt làm nội dung của tệp Scala. Chọn “Đối tượng”
Khi thực hiện việc này, chúng ta sẽ có một tệp Scala có đối tượng Singleton mà chúng ta sẽ sử dụng để chạy mã của mình.
Bây giờ bạn đã có tệp Scala với đối tượng Hello. Bạn sẽ viết chương trình đầu tiên của mình bằng cách mở rộng đối tượng bạn đã tạo bằng từ khóa Ứng dụng.
Việc mở rộng đối tượng của chúng ta bằng Ứng dụng sẽ cho trình biên dịch biết mã nào sẽ chạy khi khởi động chương trình của bạn. Ngay sau khi mở rộng Ứng dụng, một mũi tên màu xanh lục sẽ hiển thị ở phía bên trái, cho biết rằng bây giờ bạn có thể chạy chương trình của mình.
Bên trong đối tượng Hello, chúng ta viết một hàm println() được sử dụng để in văn bản bên trong nó ra bàn điều khiển. Chúng tôi sẽ chạy mã của mì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ẽ đưa ra tùy chọn Chạy, xin chào, khi nhấp vào nó, mã của chúng tôi sẽ bắt đầu biên dịch và sau vài giây, chúng tôi sẽ thấy kết quả của chương trình được in từ bảng điều khiển có sẵn trong IntelliJ IDE.
Và thế là chúng ta đã cài đặt thành công Scala và chạy chương trình đầu tiên của mình.
Bạn có thể làm gì với Scala
- Phát triển web giao diện người dùng với ScalaJS
- Phát triển di động, cả hai Android Phát triển và iOS – với Scala Native
- Các thư viện phía máy chủ như HTTP4S, Akka-Http, Play Framework
- Internet vạn vật sử dụng
- Sự phát triển trò chơi
- NLP – Xử lý ngôn ngữ tự nhiên bằng bộ thư viện ScalaNLP
- Kiểm thử các kỹ thuật lập trình nâng cao như Lập trình hàm và Lập trình hướng đối tượng
- Xây dựng ứng dụng giao tiếp đồng thời cao bằng cách sử dụng các tác nhân, thư viện dành cho JVM lấy cảm hứng từ Erlang
- Sử dụng nó để học máy bằng các thư viện như Figaro lập trình xác suất và Apache Spark việc này
Hàm ẩn danh
Ngôn ngữ Scala có các hàm ẩn danh, còn được gọi là chữ chức năng. Scala là một ngôn ngữ chức năng thường có nghĩa là các nhà phát triển chia các vấn đề lớn thành nhiều nhiệm vụ nhỏ và tạo ra nhiều hàm để giải quyết những vấn đề này. Để dễ dàng tạo các hàm, Scala chứa các hàm này mà bạn có thể sử dụng khởi tạo mà không có tên. Chúng ta có thể gán chúng trực tiếp cho các biến hoặc định nghĩa 'def' như trong ví dụ Scala bên dưới:
val multiplyByTwo = (n:Int) => n * 2 def multiplyByThree = (n:Int) => n *3
Sau đó, chúng ta có thể sử dụng các hàm theo cách thông thường bằng cách truyền tham số cho chúng theo sau.
multiplyByTwo(3) //6 multiplyByThree(4) //12
Những phương pháp này rất hữu ích khi chúng ta muốn có một đoạn mã rõ ràng và ngắn gọn. Chúng ta có thể sử dụng các hàm ẩn danh khi xác định các phương thức không lớn và không yêu cầu nhiều mã trong nội dung của chúng. Chúng rất đơn giản và không cần lễ nghi để tạo ra.
Các phương thức này không bị giới hạn ở các hàm có đối số và có thể được sử dụng để khởi tạo các phương thức không nhận bất kỳ đối số nào.
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 trong mã của chúng tôi, nơi chúng tôi cần tạo một hàm nhanh tại chỗ.
Một lý do khác tại sao các chức năng này còn được gọi là hàm nội tuyến. Sử dụng các hàm ẩn danh là một mẫu phổ biến được sử dụng rộng rãi trong thư viện bộ sưu tập để thực hiện các hành động nhanh chóng trên một bộ sưu tập.
Ví dụ: chúng tôi có phương thức lọc sử dụng hàm nội tuyến/hàm ẩn danh để tạo một bộ sưu tập khác chỉ có các phần tử đáp ứng tiêu chí mà chúng tôi xác định 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)
Ở đây, các phương thức chúng ta có dưới dạng hàm ẩn danh là những phương thức kiểm tra xem giá trị chúng ta nhận được từ danh sách có phải là số lẻ và số chẵn hay không và trả về mục đó.
//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, bạn cũng có thể sử dụng các ký tự đại diện trong đó 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, chúng tôi không đặt tên cho tham số mà chúng tôi đang truyền vào. Điều duy nhất chúng tôi sử dụng dấu gạch dưới để thể hiện nó.
Đánh giá lười biếng
Hầu hết các ngôn ngữ lần lượt đánh giá các biến và tham số hàm. Trong Scala, chúng tôi có một từ khóa tên là lười biếng, giúp xử lý các giá trị mà chúng tôi không muốn đánh giá cho đến khi chúng được tham chiếu.
Một biến được đánh dấu là lazy sẽ không được đánh giá tại nơi nó được định nghĩa, thường được gọi là đánh giá eager, nó sẽ chỉ được đánh giá khi được tham chiếu ở một thời điểm nào đó sau đó trong mã.
Điều này có thể hữu ích khi đánh giá một giá trị có thể là một phép tính tốn kém, nếu không phải lúc nào giá trị đó cũng cần thiết, chúng ta có thể tránh phải chạy một phép tính đắt tiền có thể làm chậm phần mềm của chúng ta bằng cách làm cho biến của chúng ta trở nên lười biếng.
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 cho các biến lười. Chúng cũng giúp giải quyết các vấn đề về sự phụ thuộc vòng tròn trong mã.
Trong trường hợp cài đặt sai, chúng tôi có thể không cần sử dụng myExpensiveValue, điều này có thể giúp chúng tôi tránh thực hiện một phép tính tốn kém, giúp đảm bảo rằng người dùng có thời gian vui vẻ khi sử dụng ứng dụng của chúng tôi vì các nhu cầu khác của chúng tôi có thể được tính toán chính xác mà không bị choáng ngợp RAM.
Trong trường hợp cài đặt sai, chúng tôi có thể không cần sử dụng myExpensiveValue, điều này có thể giúp chúng tôi tránh thực hiện một phép tính tốn kém, giúp đảm bảo rằng người dùng có thời gian vui vẻ khi sử dụng ứng dụng của chúng tôi vì các nhu cầu khác của chúng tôi có thể được tính toán một cách thích hợp mà không gây choáng ngợp RAM.
Tính lười biếng cũng giúp ích cho các đối số của 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ố Gọi theo tên.
def sometimesUsedString(someValue:String, defaultValue:=> String)={ if(someValue != null){ use(defaultValue) }else{ use(someValue) } }
Nhiều ngôn ngữ sử dụng phương pháp call-by-value để đánh giá các đối số. Tham số được truyền qua call-by-name sẽ chỉ được đánh giá khi cần trong thân hàm và sẽ không được đánh giá trước đó. Sau khi giá trị được đánh giá, nó được lưu trữ và có thể được sử dụng lại sau mà không cần phải đánh giá lại. Một khái niệm được gọi là memoization.
Kiểu suy luận
Trong Scala, bạn không phải khai báo loại cho mọi biến bạn tạo. Điều này là do trình biên dịch Scala có thể thực hiện suy luận kiểu dựa trên đánh giá về phía bên phải. Điều này cho phép mã của bạn ngắn gọn hơn - nó giúp chúng ta không phải viết bản soạn sẵn trong đó loại dự kiến là hiển nhiên
var first:String = "Hello, " var second:String = "World" var third = first + second //the compile infers that third is of type String
Hàm bậc cao hơn
Hàm bậc cao hơn là hàm có thể lấy hàm làm đối số và có thể trả về một hàm dưới dạng kiểu trả về. Trong Scala, các hàm được coi là công dân hạng nhất. Việc sử dụng các chức năng này theo cách này cho phép chúng tôi rất linh hoạt trong các loại chương trình mà chúng tôi có thể thực hiện. Chúng ta có thể tạo các hàm một cách linh hoạt và cung cấp chức năng một cách linh hoạt cho các hàm khác.
def doMathToInt(n:Int, myMathFunction:Int=>Int): Int ={ myMathFunction(n) }
Trong hàm trên, chúng ta truyền vào một int và một hàm nhận vào một int và trả về một int. Chúng ta có thể chuyển bất kỳ chức năng nào của chữ ký đó. Theo chữ ký, chúng tôi muốn nói đến đầu vào và đầu ra của hàm. Chữ ký của Int=>Int có nghĩa là một hàm lấy Int làm đầu vào và trả về Int làm đầu ra.
Chữ ký của ()=>Int có nghĩa là một hàm không lấy gì làm đầu vào và trả về Int làm đầu ra. Một ví dụ về hàm như vậy là hàm tạo ra một int ngẫu nhiên cho chúng ta.
def generateRandomInt()={ return scala.util.Random.nextInt() }
Hàm trên có chữ ký ()=>Int
Chúng ta có thể có một hàm có chữ ký scala ()=>Đơn vị. Điều này có nghĩa là các hàm không nhận bất cứ thứ gì và không trả về một kiểu. Hàm này có thể thực hiện một số loại tính toán bằng cách thay đổi điều gì đó thành thực hiện điều gì đó được xác định trước.
Tuy nhiên, những phương pháp này không được khuyến khích vì chúng có vẻ như là một hộp đen có thể ảnh hưởng đến hệ thống theo một số cách chưa biết. Chúng cũng không thể kiểm tra được. Có các kiểu đầu vào và đầu ra rõ ràng cho phép chúng ta suy luận về chức năng của mình.
Hàm bậc cao hơn cũng có thể trả về một hàm.
Ví dụ: chúng ta có thể tạo một phương thức sẽ tạo hàm cấp nguồn, tức là lấy một số và cấp nguồn cho nó.
def powerByFunction(n:Int):Int=>Int = { return (x:Int)=> scala.math.pow(x,n).toInt }
Hàm trên lấy một int. Kiểu trả về của chúng tôi là một hàm ẩn danh lấy Int x, * chúng tôi sử dụng int x làm đối số cho hàm power.
cà ri
Trong Scala, chúng ta có thể chuyển đổi một hàm nhận hai đối số thành một hàm nhận một đối số mỗi lần. Khi truyền vào một đối số, chúng ta áp dụng nó một phần và kết thúc bằng một hàm lấy một đối số để hoàn thành hàm. Currying cho phép chúng ta tạo các hàm bằng cách thêm một phần một số đối số.
Điều này có thể hữu ích cho việc tạo các hàm một cách linh hoạt trước khi chúng ta có một bộ đối số hoàn chỉnh
def multiply two numbers(n:Int)(m:Int): Unit ={ return n * m }
Nếu cần tạo một hàm nhân với một số cụ thể nào đó thì chúng ta không cần tạo một phương thức nhân khác.
Chúng ta có thể chỉ cần gọi .curried trong hàm ở trên và nhận một hàm nhận một đối số trước rồi trả về một hàm được áp dụng một phần
def multiplyTwoNumbers(n:Int)(m:Int): Unit ={ return n * m } var multiplyByFive = multiplyTwoNumbers(5) multiplyByFive(4) //returns 20
Khớp mẫu
Scala có một cơ chế sẵn có mạnh mẽ để giúp chúng ta kiểm tra xem một biến có khớp với các tiêu chí nhất định hay không, giống như chúng ta làm trong câu lệnh switch trong Java hoặc trong một loạt các câu lệnh if/else. Ngôn ngữ có tính năng khớp mẫu mà chúng ta có thể sử dụng để kiểm tra xem một biến có thuộc loại cụ thể hay không. So khớp mẫu trong Scala rất mạnh mẽ và có thể được sử dụng để phá hủy các thành phần có phương thức không phù hợp để lấy các trường mà chúng ta quan tâm trực tiếp từ biến mà chúng ta đang so khớp.
Việc khớp mẫu của 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 }
Chúng tôi so sánh biến của mình với một tập hợp các tùy chọn và khi biến mà chúng tôi đối sánh đáp ứng các tiêu chí, biểu thức ở phía bên phải của mũi tên béo (=>) sẽ đánh giá và được trả về dưới dạng kết quả khớp.
Chúng tôi sử dụng dấu gạch dưới để phát hiện các trường hợp không khớp trong mã của chúng tôi. Nó phản ánh hành vi của trường hợp mặc định khi xử lý các 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 _ => //case we have a type we don't recognize do sth else }
Trong đoạn mã trên, bạn có thể tìm ra loại biến myItem và dựa vào nhánh đó để đưa ra một số mã cụ thể.
Khớp mẫu kiểm tra xem biến có khớp không
Dấu gạch dưới hoạt động như một trình giữ chỗ khớp với bất kỳ điều kiện nào khác không khớp với các mục khác trong câu lệnh tình huống ở trên. Chúng ta lấy một biến myItem và gọi phương thức khớp.
- chúng tôi kiểm tra xem myItem có đúng hay không bằng cách thực hiện một số logic ở Phía bên phải của mũi tên mập “=>”.
- chúng tôi sử dụng dấu gạch dưới để khớp với bất kỳ nội dung nào không khớp với bất kỳ câu lệnh tình huống nào mà chúng tôi đã xác định trong mã.
Với các lớp Case, chúng ta thậm chí có thể tiến xa hơn và phá hủy lớp đó để lấy các trường bên trong đối tượng.
Bằng cách sử dụng từ khóa seal để xác định các lớp của mình, chúng ta có được lợi ích là nhờ trình biên dịch kiểm tra toàn diện các trường hợp mà chúng ta cố gắng so khớp và cảnh báo nếu chúng ta quên xử lý một trường hợp cụ thể.
Bất biến
Có thể tạo các giá trị mà các hàm khác không thể thay đổi trong Scala bằng từ khóa val. Điều này đạt được trong Java bằng cách sử dụng từ khóa cuối cùng. Trong Scala, chúng tôi làm như vậy bằng cách sử dụng từ khóa val khi tạo biến thay vì sử dụng var, đây là giải pháp thay thế mà chúng tôi sẽ sử dụng để tạo biến có thể thay đổi.
Một biến được xác định bằng từ khóa val là chỉ đọc, trong khi biến được xác định bằng var có thể được đọc và thay đổi bởi các hàm khác hoặc tùy ý bởi người dùng trong mã.
var changeableVariable = 8 changeableVariable =10 //the compiler doesn't complain, and the code compiles successfully println(changeableVariable) //10 val myNumber = 7 myNumber = 4 //if we try this the code won't compile
Việc cố gắng gán một giá trị cho myNumber sau khi chúng ta đã khai báo nó dưới dạng val sẽ gây ra lỗi thời gian biên dịch hoặc “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 chúng tôi ngăn chặn mã và các lập trình viên khác thay đổi giá trị của chúng tôi một cách bất ngờ, điều này sẽ dẫn đến kết quả không mong muốn nếu họ có ý định sử dụng giá trị mà chúng tôi lưu trữ, thay vào đó họ có thể tạo một bản sao của giá trị đó. Bằng cách này, các lỗi có thể xảy ra do nhiều tác nhân thay đổi cùng một biến sẽ được ngăn chặn.
Lớp và Đối tượng
Tất cả chúng ta đều biết rằng các đối tượng là các thực thể trong thế giới thực và lớp là một khuôn mẫu xác định các đối tượng. Các lớp có cả trạng thái và hành vi. Các trạng thái là giá trị hoặc biến. Các hành vi là các phương thức trong Scala.
Chúng ta hãy xem cách bạn có thể định nghĩa một lớp, khởi tạo nó và sử dụng nó bằng Scala.
Ở đây, lớp có tên là Rectangle, có hai biến và hai hàm. Bạn cũng có thể sử dụng trực tiếp các tham số l và b làm các trường trong chương trình. Bạn có một đối tượng có một phương thức chính 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 rectangle with length as $length and breadth as $breadth" } object RectObject { def main(args: Array[String]) { val rect = new Rectangle(4, 5) println(rect.toString) println(rect.getArea) } }
Tất cả các trường và phương thức theo mặc định đều ở chế độ công khai trong Scala. Việc sử dụng ghi đè là điều cần thiết vì phương thức toString được xác định cho Object trong Scala.
di sản
Scala có nhiều loại kế thừa (như đơn, đa cấp, nhiều cấp, phân cấp, 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 Java. Bạn có thể kế thừa cả từ lớp và đặc điểm. Bạn có thể kế thừa các thành viên của lớp này sang 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 có siêu lớp, tạo ra hệ thống phân cấp kế thừa trong quy trình.
Trong ví dụ Scala bên dưới, lớp Cơ sở là Circle và lớp dẫn xuất là Sphere. Một vòng tròn có một giá trị gọi là bán kính, được kế thừa trong lớp Sphere. Phương thức calcArea được ghi đè bằng từ khóa ghi đè.
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 } }
Trừu tượng
Trong Scala, chúng ta có thể tạo các phương thức trừu tượng và các trường thành viên bằng cách sử dụng các đặc điểm và lớp trừu tượng. Bên trong các lớp và đặc điểm trừu tượng, chúng ta có thể định nghĩa các trường trừu tượng mà không nhất thiết phải 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 lớp đặc điểm hoặc lớp trừu tượng. Bạn có thể sử dụng các đặc điểm để tạo hợp đồng về những gì ứng dụng của chúng ta có thể làm và sau đó triển khai các phương thức đó sau.
trait DatabaseService{ def addItemName(itemName:String) def removeItem(itemId:Int) def updateItem(itemId:Int, newItemName:String) }
Bằng cách này, chúng ta có thể lên kế hoạch cho ứng dụng của mình sẽ trông như thế nào mà không cần triển khai các phương pháp có thể giúp chúng ta hình dung các phương pháp khác nhau sẽ trông như thế nào. Nó tuân theo một mô hình được gọi là lập trình trừu tượng chứ không phải triển khai thực tế.
Lớp được mở đầu bằng từ khóa tóm tắt có thể chứa cả phương thức trừu tượng và không trừu tượng. Tuy nhiên, tính năng đa kế thừa không được hỗ trợ trong lớp trừu tượng. Vì vậy, bạn có thể mở rộng tối đa một lớp trừu tượng.
Đối tượng đơn
Singleton là lớp chỉ được khởi tạo một lần trong chương trình. Đó là từ một mẫu lập trình phổ biến và hữu ích được gọi là “mẫu đơn”. Điều này hữu ích trong việc tạo các phiên bản có mục đích tồn tại lâu dài và sẽ được truy cập phổ biến trong toàn bộ chương trình của bạn, trạng thái của phiên bản này là không thể thiếu trong việc điều phối các sự kiện của hệ thống. Tạo một lớp như vậy trong Scala thật dễ dàng vì Scala cung cấp cho chúng ta một phương tiện đơn giản để tạo các singleton bằng cách sử dụng từ khóa object.
object UserProfile{ var userName="" var isLoggedIn:Boolean = false }
Sau đó, chúng tôi có thể tham chiếu đối tượng này trong suốt chương trình của mình với sự đảm bảo rằng tất cả các phần trong chương trình của chúng tôi sẽ thấy cùng một dữ liệu vì chỉ có một phiên bản 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 có trong Scala, đó là lý do bạn cần sử dụng các đối tượng đơn lẻ, hoạt động giống như các thành viên tĩnh của một lớp.
Lớp ngầm
Các lớp tiềm ẩn là chức năng mới được thêm vào sau phiên bản 2.1. Chủ yếu là thêm chức năng mới vào các lớp đã đóng.
Từ khóa ngầm phải được xác định trong một lớp, đối tượng hoặc đặc điểm. Hàm tạo chính của một lớp ẩn 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ố tiềm ẩn 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 Chuỗi bằng * được thêm vào.
object StringUtil { implicit class StringEnhancer(str: String) { def replaceVowelWithStar: String = str.replaceAll("[aeiou]", "*") } }
Bạn cần nhập vào lớp nơi 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 các chương trình OOP được xây dựng bằng cách nhóm dữ liệu và các chức năng hoạt động trên dữ liệu đó thành các đơn vị có tính kết nối cao. Các đối tượng mang dữ liệu của chúng trong các trường và phương thức hoạt động trên chúng. Trong phong cách lập trình này, sự trừu tượng hóa chính là dữ liệu vì các phương thức được tạo ra nhằm hoạt động trên dữ liệu.
Lập trình chức năngmặt khác, phân tách dữ liệu và các chức năng 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 chức năng là sự trừu tượng hóa và động lực khi lập mô hình chương trình.
Scala cho phép lập trình chức năng bằng cách coi các hàm là công dân hạng nhất, cho phép chúng được truyền dưới dạng giá trị cho các hàm khác và cũng được trả về dưới dạng giá trị. Sự kết hợp của hai mô hình này đã biến Scala trở thành lựa chọn tuyệt vời trong việc xây dựng phần mềm phức tạp trong nhiều ngành công nghiệp khác nhau, chẳng hạn 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 của 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 theo Apache, Nó đã trở thành framework phổ biến nhất trên GitHub vào năm 2013. Các công ty như LinkedIn, Walmart, Samsung, Eero sử dụng framework này.
- thang máy là một khung web miễn phí khác được viết bằng Scala ra mắt năm 2007. Foursquare sử dụng khung Lift. Nó có hiệu suất cao, xây dựng framework nhanh hơn.
- mẫu Anh
- Mèo
- Spark
Hỗ trợ đồng thời
- Các giá trị trong Scala theo mặc định là không thay đổi. Điều này làm cho nó rất thích nghi với môi trường đồng thời.
- Có rất nhiều tính năng trong Scala giúp nó trở nên tốt nhất cho các ứng dụng đồ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 – bộ công cụ sử dụng mô hình đồng thời của Actor. Có một số Diễn viên hành động khi họ nhận được tin nhắn.
- Đồng thời sử dụng các luồng từ Java cũng có thể được hỗ trợ trong Scala.
- Xử lý luồng 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ủ đề
- Sợi từ các thư viện như Vertex
- ZIO – một thư viện có các nguyên hàm giúp chúng ta xử lý tính toán đồng thời và không đồng bộ
- STM – Giao dịch
- Tương lai – có sẵn bằng ngôn ngữ Scala
Java so với Scala
Đây là chính sự khác biệt giữa Java và Scala.
Scala | Java |
---|---|
Nhỏ gọn và súc tích hơn | Các đoạn mã tương đối lớn hơn |
Được thiết kế và phát triển để trở thành ngôn ngữ 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ư đồng thời, Bất biến. |
Ban đầu được phát triển như một ngôn ngữ 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 những ngày gần đây. Vẫn không mạnh bằng ngôn ngữ lập trình chức năng. |
Sử dụng mô hình diễn viên để hỗ trợ đồng thời hiện đạ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 – Play, Lift | Hỗ trợ Spring, Grails, nhiều hơn nữa |
Hỗ trợ đánh giá lười biếng | Không hỗ trợ đánh giá lười biếng |
Không có thành viên tĩnh | Chứa thành viên tĩnh |
Hỗ trợ quá tải toán tử | Không hỗ trợ quá tải toán tử |
Quá trình biên dịch mã nguồn tương đối chậm | Biên dịch mã nguồn nhanh hơn Scala |
Đặc điểm – hành động như thế 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 |
Cần viết lại | Viết lại là không cần thiết |
Không đảm bảo về mã không có lỗi | Đảm bảo hoàn toàn các khiếm khuyết nhỏ hơn |
Hỗ trợ khả năng tương thích ngược. | Scala không hỗ trợ khả năng tương thích ngược. |
Operators được đối xử khác nhau trong Java và không phải là cuộc gọi phương thức. | Tất cả các toán tử trên các mục đều thông qua một phương thức có tên trong Scala. |
Hỗ trợ nhiều kế thừa bằng cách sử dụng các lớp nhưng không phải bằng các lớp trừu tượng | Không hỗ trợ đa kế thừa bằng cách sử dụng các lớp mà bằng giao diện |
Mã được viết ở dạng nhỏ gọn. | Mã được viết ở dạng dài. |
Scala không chứa từ khóa tĩnh. | Java chứa từ khóa tĩnh. |
Tổng kết
Trong hướng dẫn này, bạn đã học cách bắt đầu với Scala. Bạn cũng đã học các tính năng chức năng và hướng đối tượng. Bạn cũng đã phát hiện ra những điểm tương đồng và khác biệt giữa Java và Scala. Hướng dẫn này lẽ ra đã giúp bạn với rất nhiều ví dụ được thể hiện rõ ràng.