Operatörleri öğretim amacıyla dört kategoriye ayırıyorum :
- Anahtar kelimeler / ayrılmış simgeler
- Otomatik olarak içe aktarılan yöntemler
- Ortak yöntemler
- Sözdizimsel şekerler / kompozisyon
O halde, çoğu kategorinin soruda temsil edilmesi şanslı:
-> // 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
Bu yöntemlerin çoğunun kesin anlamı, onları tanımlayan sınıfa bağlıdır. Örneğin, <=
ilgili Int
vasıtasıyla "daha az ya da eşit" . Birincisi, ->
aşağıda örnek olarak vereceğim. ::
muhtemelen aynı yöntemde tanımlanmış yöntemdir List
( aynı adın nesnesi de olabilir ) ve :+=
muhtemelen çeşitli Buffer
sınıflarda tanımlanan yöntemdir .
Öyleyse görelim.
Anahtar kelimeler / ayrılmış simgeler
Scala'da özel olan bazı semboller var. Bunlardan ikisi uygun anahtar kelimeler olarak kabul edilirken, diğerleri yalnızca "ayrılmış" olarak kabul edilir. Onlar:
// 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
Bunların hepsi dilin bir parçasıdır ve bu nedenle dili doğru tanımlayan herhangi bir metinde bulunabilir, örneğin Scala Spesifikasyonu (PDF).
Sonuncusu, alt çizgi, özel bir açıklamayı hak ediyor, çünkü çok yaygın olarak kullanılıyor ve çok farklı anlamları var. İşte bir örnek:
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
Yine de muhtemelen başka bir anlam unuttum.
Otomatik olarak içe aktarılan yöntemler
Bu nedenle, aradığınız sembolü yukarıdaki listede bulamadıysanız, bu bir yöntem veya birinin bir parçası olmalıdır. Ancak, genellikle, bazı semboller görürsünüz ve sınıfın belgelerinde bu yöntem bulunmaz. Bu olduğunda, ya bir ya da daha fazla yöntemin başka bir şeyle bir bileşimine bakıyorsunuz ya da yöntem kapsama alınmış ya da içe aktarılan bir örtük dönüştürme yoluyla kullanılabilir.
Bunlar hala bulunabilir üzerinde ScalaDoc : sadece burada onları aramak için bilmek zorunda. Ya da başarısız olursa, dizine bakın (şu anda 2.9.1'de kırılmıştır, ancak her gece mevcuttur).
Her Scala kodunda üç otomatik ithalat vardır:
// Not necessarily in this order
import _root_.java.lang._ // _root_ denotes an absolute path
import _root_.scala._
import _root_.scala.Predef._
İlk ikisi sadece sınıfları ve singleton nesnelerini kullanılabilir kılar. Üçüncüsü Predef
, bir nesnenin kendisi olduğu için tüm örtük dönüşümleri ve içe aktarılan yöntemleri içerir .
İçeriye Predef
hızlıca bakmak bazı sembolleri gösterir:
class <:<
class =:=
object <%<
object =:=
Diğer tüm semboller, örtük bir dönüştürme yoluyla kullanılabilir hale getirilir . implicit
Bu alıcı ile etiketlenen metotlara , parametre olarak, metodu alan tipte bir nesneye bakmanız yeterlidir . Örneğin:
"a" -> 1 // Look for an implicit from String, AnyRef, Any or type parameter
Yukarıdaki durumda, ->
sınıfta bir nesne türünü ArrowAssoc
alan yöntemle tanımlanır ; buradaany2ArrowAssoc
A
A
aynı yönteme bağlı olmayan bir tür parametresidir.
Ortak yöntemler
Yani, birçok sembol bir sınıftaki yöntemlerdir. Örneğin,
List(1, 2) ++ List(3, 4)
Yöntemi ++
doğrudan ScalaDoc for List'te bulabilirsiniz . Bununla birlikte, yöntemleri ararken farkında olmanız gereken bir kural vardır. İki nokta üst üste ( :
) ile biten yöntemler sol yerine sağa bağlanır . Başka bir deyişle, yukarıdaki yöntem çağrısı şuna eşdeğerdir:
List(1, 2).++(List(3, 4))
Ben bunun yerine 1 :: List(2, 3)
, bu eşdeğer olurdu:
List(2, 3).::(1)
Bu nedenle , iki nokta üst üste ile biten yöntemleri ararken sağda bulunan türe bakmanız gerekir . Örneğin şunu düşünün:
1 +: List(2, 3) :+ 4
İlk yöntem ( +:
) sağa bağlanır ve üzerinde bulunur List
. İkinci yöntem ( :+
) sadece normal bir yöntemdir ve sola bağlanır - tekrar, açıkList
.
Sözdizimsel şekerler / kompozisyon
Yani, bir yöntemi gizleyebilecek birkaç söz dizimi şekeri:
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
Sonuncusu ilginçtir, çünkü herhangi bir sembolik yöntem bu şekilde bir atama benzeri yöntem oluşturmak için birleştirilebilir.
Ve elbette, kodda görünebilecek çeşitli kombinasyonlar var:
(_+_) // 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.