Tôi chia các toán tử, cho mục đích giảng dạy, thành bốn loại :
- Từ khóa / ký hiệu dành riêng
- Phương thức nhập tự động
- Phương pháp phổ biến
- Đường tổng hợp / thành phần
Sau đó, thật may mắn là hầu hết các danh mục được thể hiện trong câu hỏi:
-> // Automatically imported method
||= // Syntactic sugar
++= // Syntactic sugar/composition or common method
<= // Common method
_._ // Typo, though it's probably based on Keyword/composition
:: // Common method
:+= // Common method
Ý nghĩa chính xác của hầu hết các phương thức này phụ thuộc vào lớp định nghĩa chúng. Ví dụ: <=
trên Int
có nghĩa là "nhỏ hơn hoặc bằng" . Cái đầu tiên ->
, tôi sẽ đưa ra ví dụ dưới đây. ::
có lẽ là phương thức được định nghĩa trên List
(mặc dù nó có thể là đối tượng cùng tên) và :+=
có lẽ là phương thức được định nghĩa trên các Buffer
lớp khác nhau .
Vì vậy, hãy xem chúng.
Từ khóa / ký hiệu dành riêng
Có một số biểu tượng trong Scala là đặc biệt. Hai trong số chúng được coi là từ khóa thích hợp, trong khi những từ khác chỉ là "dành riêng". Họ đang:
// Keywords
<- // Used on for-comprehensions, to separate pattern from generator
=> // Used for function types, function literals and import renaming
// Reserved
( ) // Delimit expressions and parameters
[ ] // Delimit type parameters
{ } // Delimit blocks
. // Method call and path separator
// /* */ // Comments
# // Used in type notations
: // Type ascription or context bounds
<: >: <% // Upper, lower and view bounds
<? <! // Start token for various XML elements
" """ // Strings
' // Indicate symbols and characters
@ // Annotations and variable binding on pattern matching
` // Denote constant or enable arbitrary identifiers
, // Parameter separator
; // Statement separator
_* // vararg expansion
_ // Many different meanings
Đây là tất cả các phần của ngôn ngữ , và, như vậy, có thể được tìm thấy trong bất kỳ văn bản nào mô tả chính xác ngôn ngữ, chẳng hạn như chính Đặc tả Scala (PDF).
Cái cuối cùng, dấu gạch dưới, xứng đáng được mô tả đặc biệt, bởi vì nó được sử dụng rộng rãi và có rất nhiều ý nghĩa khác nhau. Đây là một mẫu:
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence
Tôi có lẽ đã quên một số ý nghĩa khác, mặc dù.
Phương thức nhập tự động
Vì vậy, nếu bạn không tìm thấy biểu tượng bạn đang tìm kiếm trong danh sách trên, thì đó phải là một phương thức hoặc một phần của một biểu tượng. Nhưng, thông thường, bạn sẽ thấy một số biểu tượng và tài liệu cho lớp sẽ không có phương pháp đó. Khi điều này xảy ra, hoặc bạn đang xem một thành phần của một hoặc nhiều phương thức với một phương thức khác hoặc phương thức đã được nhập vào phạm vi hoặc có sẵn thông qua một chuyển đổi ẩn được nhập.
Chúng vẫn có thể được tìm thấy trên ScalaDoc : bạn chỉ cần biết nơi để tìm chúng. Hoặc, không thành công, hãy nhìn vào chỉ số (hiện đã bị hỏng vào ngày 2.9.1, nhưng có sẵn vào ban đêm).
Mỗi mã Scala có ba lần nhập tự động:
// Not necessarily in this order
import _root_.java.lang._ // _root_ denotes an absolute path
import _root_.scala._
import _root_.scala.Predef._
Hai cái đầu tiên chỉ làm cho các lớp và các đối tượng singleton có sẵn. Cái thứ ba chứa tất cả các chuyển đổi ngầm định và các phương thức được nhập, vì Predef
chính nó là một đối tượng.
Nhìn vào bên trong Predef
nhanh chóng hiển thị một số biểu tượng:
class <:<
class =:=
object <%<
object =:=
Bất kỳ biểu tượng nào khác sẽ được cung cấp thông qua một chuyển đổi ngầm . Chỉ cần nhìn vào các phương thức được gắn thẻ implicit
nhận, như tham số, một đối tượng của kiểu đang nhận phương thức. Ví dụ:
"a" -> 1 // Look for an implicit from String, AnyRef, Any or type parameter
Trong trường hợp trên, ->
được định nghĩa trong lớp ArrowAssoc
thông qua phương thức any2ArrowAssoc
lấy một đối tượng kiểu A
, trong đó A
tham số kiểu không giới hạn cho cùng một phương thức.
Phương pháp phổ biến
Vì vậy, nhiều biểu tượng chỉ đơn giản là các phương thức trên một lớp. Ví dụ, nếu bạn làm
List(1, 2) ++ List(3, 4)
Bạn sẽ tìm thấy phương pháp ++
ngay trên ScalaDoc cho Danh sách . Tuy nhiên, có một quy ước mà bạn phải biết khi tìm kiếm các phương thức. Các phương thức kết thúc bằng dấu hai chấm ( :
) liên kết với bên phải thay vì bên trái. Nói cách khác, trong khi cuộc gọi phương thức trên tương đương với:
List(1, 2).++(List(3, 4))
Nếu tôi có, thay vào đó 1 :: List(2, 3)
, nó sẽ tương đương với:
List(2, 3).::(1)
Vì vậy, bạn cần nhìn vào loại được tìm thấy ở bên phải khi tìm kiếm các phương thức kết thúc bằng dấu hai chấm. Xem xét, ví dụ:
1 +: List(2, 3) :+ 4
Phương thức đầu tiên ( +:
) liên kết với bên phải và được tìm thấy trên List
. Phương thức thứ hai ( :+
) chỉ là một phương thức bình thường và liên kết với bên trái - một lần nữa, trên List
.
Đường tổng hợp / thành phần
Vì vậy, đây là một vài loại đường cú pháp có thể ẩn một phương thức:
class Example(arr: Array[Int] = Array.fill(5)(0)) {
def apply(n: Int) = arr(n)
def update(n: Int, v: Int) = arr(n) = v
def a = arr(0); def a_=(v: Int) = arr(0) = v
def b = arr(1); def b_=(v: Int) = arr(1) = v
def c = arr(2); def c_=(v: Int) = arr(2) = v
def d = arr(3); def d_=(v: Int) = arr(3) = v
def e = arr(4); def e_=(v: Int) = arr(4) = v
def +(v: Int) = new Example(arr map (_ + v))
def unapply(n: Int) = if (arr.indices contains n) Some(arr(n)) else None
}
val Ex = new Example // or var for the last example
println(Ex(0)) // calls apply(0)
Ex(0) = 2 // calls update(0, 2)
Ex.b = 3 // calls b_=(3)
// This requires Ex to be a "val"
val Ex(c) = 2 // calls unapply(2) and assigns result to c
// This requires Ex to be a "var"
Ex += 1 // substituted for Ex = Ex + 1
Cách cuối cùng là thú vị, bởi vì bất kỳ phương thức biểu tượng nào cũng có thể được kết hợp để tạo thành một phương thức giống như bài tập theo cách đó.
Và, tất nhiên, có nhiều kết hợp khác nhau có thể xuất hiện trong mã:
(_+_) // An expression, or parameter, that is an anonymous function with
// two parameters, used exactly where the underscores appear, and
// which calls the "+" method on the first parameter passing the
// second parameter as argument.