快學(xué)Scala讀書筆記

scala不刻意區(qū)分原生類型和引用類型

scala單參數(shù)方法可以用運(yùn)算符形式調(diào)用,例如:

// 這兩種寫法等效
a.add(b)
a add b

scala沒有提供"++" 和 "--" 運(yùn)算符,可以使用:

a += 1
a -= 1

import scala開頭的包可以省略scala前綴

// 以下寫法等效
import scala.collection.mutable.Map
import collection.mutable.Map

apply方法可以直接在類名或者實(shí)例變量名后直接用小括號(hào)來調(diào)用

class Demo {
  def apply(n: int): Unit = {}
}

可以這么調(diào)用

val demo = new Demo
demo(6) //相當(dāng)于demo.apply(6)
object Demo {
  def apply(n: int): Unit = {}
}

可以這么調(diào)用

Demo(6)

這種寫法多用于構(gòu)建對(duì)象坝初,例如:

object Demo {
  def apply(n: Int) = {
    val demo = new Demo
    demo.setXXX
    // ...
    demo
  }
}
class Demo {
  // ...
}

scala沒有checked exception

scala中if 和 else是一個(gè)表達(dá)式,因此可以這么使用:

val a = if (1 > 0) 1 else 0

如果這樣寫:

val a = if (1 < 0) 1

則相當(dāng)于:

val a = if (1 < 0) 1 else ()

()是一個(gè)Unit類,代表無(wú)值

{}代碼塊包含一系列表達(dá)式疾呻,代碼塊的值就是最后一個(gè)表達(dá)式的值

val s = {
  val a, b = 1
  a + b
}
// s == 2

代碼塊如果最后一條語(yǔ)句為賦值語(yǔ)句,則代碼塊的值為Unit写半,例如:

{
  var n = 0
  n += 1
}

readLine函數(shù)從控制臺(tái)讀取輸入:

val str = readLine("Please input a string")

for循環(huán):

for (i <- 0 to 10) {}
// i 從0到10岸蜗,包含0和10

for(i <- 0 until 10) {}
// i 從0到10,包含0不包含10

// 取字符串中每一個(gè)char可以使用循環(huán):
for(s <- "Hello") {}

scala for循環(huán)沒有break和continue叠蝇,如果想break可以使用:

import scala.util.control.Breaks._
breakable {
  for (s <- 1 to 10) {
    if (...) break
  }
}

高級(jí)for循環(huán):

for (i <- 1 to 3; j <- 1 to 3) println(i *10 + j)

推導(dǎo)式中可以帶守衛(wèi):

for (i <- 1 to 3; j <- 1 to 3 if i != j) println(i *10 + j)

可以在for循環(huán)中定義變量:

for (i <- 1 to 3; from = 4 - i; j <- from to 3) println(i *10 + j)

for循環(huán)的循環(huán)體以yield開始可以構(gòu)造出一個(gè)新的集合:

val collection = for (i <- 1 to 3; from = 4 - i; j <- from to 3) yield i *10 + j

函數(shù)無(wú)需指明返回類型璃岳,但是遞歸函數(shù)必須指明

函數(shù)參數(shù)可以指定默認(rèn)值:

def add (x: int, y: int = 1) = {x + y}

add(1) // 返回2
add(1,3) // 返回4

變長(zhǎng)參數(shù):

def add (x: int, y: int*) {
  // y被認(rèn)為是數(shù)組
  for(i <- y) {}
}

集合轉(zhuǎn)換成變長(zhǎng)序列:

val a = 1 to 5
add(1, a: _*)

懶值:懶值介于val和def之間

val result = ... // 被定義的時(shí)候執(zhí)行
lazy val result = ... // 第一次使用的時(shí)候執(zhí)行
def result = ... // 每一次使用的時(shí)候都執(zhí)行

throw表達(dá)式的類型為Nothing。if/else中如果一個(gè)分支的類型為Nothing則表達(dá)式的類型為另一個(gè)分支的類型:

if (x >=0) {sqrt(x)} else throw new IllegalArgumentException("...") //類型為Double

異常捕獲采用的是模式匹配:

try {
...
} catch {
  case _: ExceptionA => print("...")
  case e: ExceptionB => e.printStackTrace()
}

定長(zhǎng)數(shù)組時(shí)Array悔捶,變長(zhǎng)數(shù)組為ArrayBuffer

定義數(shù)組:

val arr = new Array[Int](10) // 定義數(shù)組arr铃慷,長(zhǎng)度為10,類型為Int蜕该,所有值初始化為0
val stringArr = Array("Hello", "World")
val s = stringArr(0) // 值為"Hello"

ArrayBuffer運(yùn)算:

val a = new ArrayBuffer[int]()
a += 1// a為 (1)
a += (2, 3, 4, 5) // a為 (1, 2, 3, 4, 5)
a ++= Array(6, 7, 8, 9, 10) // a為(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
a.trimEnd(5) // a為 (1, 2, 3, 4, 5)
b.insert(index, 被插入元素序列)
b.remove(起始index, 移除元素個(gè)數(shù))

ArrayBuffer 轉(zhuǎn)換為 Array

arr.toArray

遍歷數(shù)組

for(i <- 0 until a.length) {} // 使用index
for(e <- a) {} // 不使用index

0 until (a.length, 2) // step為2
(0 until a.length).reverse // 逆序

數(shù)組常用方法:

  • sum
  • max
  • sorted
  • scala.util.Sorting.quickSort
  • mkString

多維數(shù)組:

val a = Array.ofDim[Double](3, 4) // 3行4列
a(4)(2)

構(gòu)造Map:

val map = Map("key1" -> 1, "key2" -> 2) // 不可變map
val map = scala.collection.mutable.Map("key1" -> 1, "key2" -> 2) // 可變map

映射是對(duì)偶的集合犁柜,"key1" -> 1 構(gòu)造了一個(gè)對(duì)偶,相當(dāng)于("key1", 1)堂淡,因此map可以這樣構(gòu)造:

val map = Map(("key1", 1), ("key2", 2))

獲取map的值:

val value = map("key1")

map是否存在key:

map.contains("key")

map.getOrElse("key", 0) // key存在則返回key對(duì)應(yīng)的值赁温,否則返回0
map.get("key") // 返回Option對(duì)象,要么是Some(值)淤齐,要么是None

更新可變映射:

map("key") = 1
map += ("key3" -> 3, "key4" -> 4)
map -= "key4" // 移除key為"key4"的entry

遍歷映射:

for((key, value) <- map) {}
for((key, value) <- map) yield (value, key) // 反轉(zhuǎn)映射

map.keySet // 返回鍵的集合
map.values // 返回值的集合

元組

val tuple = (1, "Paul")
val name = tuple._1 // 返回1股囊,下標(biāo)從1開始而不是0
val (id, name) = tuple // id為1,name為Paul
val (id, _) = tuple // id 為1

patition分區(qū)操作:

"ABCdef".patition(_.isUpper) // 返回("ABC", "def")

zip操作:

val a = Array("a", "b", "c")
val b = Array(1, 2, 3)
val c = a.zip(b) // c為Array(("a", 1), ("b", 2), ("c", 3))

對(duì)偶的集合可以使用toMap轉(zhuǎn)換為map

方法的調(diào)用:

class A {
  def func() = {}
}

可以使用a.func()或者a.func方式調(diào)用更啄,但是定義時(shí)候如果沒有給出小括號(hào)稚疹,例如:

class A {
  def func = {}
}

則只能使用a.func方式調(diào)用

如果成員變量的名字為a,則在scalar中a的getter方法名為a,setter方法名為a_=

var變量會(huì)自動(dòng)生成setter和getter
如果變量是private的則setter和getter都是private的
val聲明的變量只有g(shù)etter方法
private[this]變量沒有setter和getter方法

privateprivate[this]的區(qū)別

class Counter {
  private var count = 0
  def isLess(other: Counter) = count < other.count
  // 雖然count是private類型變量内狗,但是other是Counter類型怪嫌,因此在    Counter內(nèi)部能夠正常訪問
  // 此處counter若為private[this],Counter類只能訪問當(dāng)前對(duì)象的count變量
}

自動(dòng)生成java bean的setter和getter方法

@BeanProperty var a = 0

主構(gòu)造器:

class Student(val name: String, val age: Int)

主構(gòu)造器會(huì)執(zhí)行類定義中的所有語(yǔ)句

如果聲明構(gòu)造器參數(shù)沒有指明val或者var柳沙,則生成的字段為private[this]岩灭。若該字段未被使用則不會(huì)生成該字段。

私有化主構(gòu)造器:

class Person private (val name: String)

類型投影:

ArrayBuffer[Network#Member] // 任意Network實(shí)例中的Member對(duì)象

單例對(duì)象:

object Person {
}
```scala

main函數(shù):
```scala
object Demo {
  def main(args: Array[String]) {}
}

也可以擴(kuò)展App特質(zhì):

object Demo extends App {
  // main函數(shù)執(zhí)行的內(nèi)容
}

枚舉類型

object Direction extend Enumeration {
  type Direction = Value
  val EAST, WEST, SOUTH, NORTH = Value
}

包可以寫成嵌套格式:

package com {
  package paul {
    class A
  }
}

scala中的包名是相對(duì)的赂鲤,如果要使用絕對(duì)包名噪径,需要以root開始

包對(duì)象:
每個(gè)包都有一個(gè)包對(duì)象,需要在父包中定義它数初,名字和子包一樣找爱。

package object people {}

引入包的全部成員:

import com.paul._

scala中import語(yǔ)句可以出現(xiàn)在任何地方,不局限于文件頂部

包選取器泡孩,用于引入包中的幾個(gè)成員:

import java.awt.{Color, Font}
import java.util.{HashMap => JavaHashMap} //使用別名

重寫方法必須使用override修飾符

isInstanceOf() // 檢查類型
asInstanceOf() // 轉(zhuǎn)換類型

如果只想測(cè)試p是不是某一個(gè)特定的類而不是其子類的話车摄,可以:

if (p.getClass == classOf[A]) {}

scala中protected字段對(duì)于同一個(gè)包的其他類而言是不可見的,只有它的子類可見仑鸥。這點(diǎn)和Java是不同的

超類構(gòu)造器:

class Person(val name: String)
class User(val name: String, val password: String) extends Person(name)

def只能重寫def
val只能重寫另一個(gè)val或不帶參數(shù)的def
var只能重寫另一個(gè)抽象的var

提前定義:

class Ant extends {
  override val range = 2
} with Creature

重寫變量range會(huì)在Creature構(gòu)造函數(shù)之前執(zhí)行

scala檢查對(duì)象是否相等可以用==運(yùn)算符

讀取文件行:

import scala.io.Source
val source = Source.fromFile("myFile.txt", "UTF-8")
val lineIterator = source.getLines
for (line <- lineIterator) {}
source.close()
for (c <- source) {} // 處理單個(gè)字符

val iter = source.buffered
iter.head // peek下一個(gè)字符吮播,但不取出
從URL或者是其他源讀取數(shù)據(jù):
val source1 = Source.fromURL()
val source1 = Source.fromString("Hello World")
val source3 = Source.fromStdin()

讀取二進(jìn)制文件需要使用Java的類庫(kù)

Scala序列化:

@SerialVersionUID(42L) class Person extends Serialization

如果使用默認(rèn)的SerialVersionUID可以省略該注解

scala執(zhí)行系統(tǒng)命令:

import system.process._
"ls -al .." ! // 執(zhí)行結(jié)果被打印到標(biāo)準(zhǔn)輸出
!返回結(jié)果是被執(zhí)行程序的返回值眼俊,如果正常返回0薄料,否則顯示非0值

val result = "ls -al .." !! // 輸出結(jié)果會(huì)以字符串的形式返回

"ls -al .." #| "grep sec" ! // #| 為管道操作符

"ls -al .." #> new File("file.txt") ! // 輸出重定向到文件
"ls -al .." #>> new File("file.txt") ! // 輸出追加到文件末尾
"grep sec" #< new File("output.txt") ! // 文件內(nèi)容作為輸入
"grep sec" #< new File("output.txt") ! // URL內(nèi)容作為輸入

p #&& q // 如果p成功,執(zhí)行q
p #|| q // 如果p不成功泵琳,執(zhí)行q

正則表達(dá)式:

val regexp = """[abc]{1,3}""".r // String的r方法生成正則表達(dá)式。為了避免轉(zhuǎn)義誊役,可以使用原始字符串語(yǔ)法:"""..."""

迭代匹配值:

for (matching <- regexp.findAllIn("...")) {}

匹配值轉(zhuǎn)換為數(shù)組:

val matches = regexp.findAllIn("...").toArray

其他正則表達(dá)式方法:
findfirstIn, findPrefixOf, replaceFirstIn, replaceAllIn

正則表達(dá)式組:

val numItemPattern = """(\d+) ([A-Za-z]+)""".r

匹配組:

val numItemPattern (num, item) = "99 bottles"

匹配多個(gè)組

for (numItemPattern (num, item) <- numItemPatter.findAllIn("99 bottles, 100 kettles"))

實(shí)現(xiàn)多個(gè)特質(zhì):

class A extend B with C with D

如果特質(zhì)中方法已經(jīng)實(shí)現(xiàn)获列,子類中重寫該方法必須要添加override關(guān)鍵字。如果特質(zhì)中方法未實(shí)現(xiàn)击孩,則寫不寫override均可

class A extends B with C {
  def f = {
    super.func()
    // 如果特質(zhì)B和C中都有方法func鹏漆,則按照從左到右的優(yōu)先循序,執(zhí)行B中的func方法

    super[C].func()
    // 明確指明調(diào)用特質(zhì)C中的func方法
  }
}

特質(zhì)中出現(xiàn)的具體字段會(huì)被添加到子類中

trait Parent {
  val count = 0
}

class Child extends Parent {
  // 相當(dāng)于也加入了val count = 0
}

特質(zhì)不能有構(gòu)造器參數(shù)括蝠,每個(gè)特質(zhì)都有一個(gè)無(wú)參數(shù)構(gòu)造器饭聚。

特質(zhì)可以擴(kuò)展類秒梳,該類會(huì)自動(dòng)成為混入該特質(zhì)的類的超類

自身類型:
特質(zhì)可以以如下代碼開始:

this: 類型A =>
...

如此定義的特質(zhì)只能被混入類型A的子類當(dāng)中

自身類型也可以處理結(jié)構(gòu)類型:

trait A {
this: {def getMessage(): Unit} =>
...
// 只有具有g(shù)etMessage方法的類才能混入該特質(zhì)
}

yield事scala的保留字箕速,如果調(diào)用java的方法中包含該單詞朋譬,需要反引號(hào)。例如:Thread.yield

定義前置操作符:

class A {
  def unary_-(): Unit = {}
}

調(diào)用該前置操作符時(shí)可使用:-a字柠,相當(dāng)于a.unary_-

用于構(gòu)造列表的::操作符是右結(jié)合的:
1 :: 2 :: Nil的意思是1 :: (2 :: Nil)
2 :: Nil 相當(dāng)于Nil.::(2)

函數(shù)調(diào)用語(yǔ)法可以擴(kuò)展到函數(shù)之外的值犀忱,例如:
f(x, y, z) 相當(dāng)于調(diào)用f.apply(x, y, z)
f(x, y, z) = value 相當(dāng)于調(diào)用f.update(x, y, z, value)

提取器:

class Fraction(val num: Int, val den: Int)

object Fraction {
  def unapply(input: Fraction): Option[(Int, Int)] = {
    if (input.den == 0) None else Some((input.num, input.den))
  }
}
val Fraction(a, b) = new Fraction(3, 4) // a 為 3, b 為 4
// unapply方法用在賦值語(yǔ)句和模式匹配中

unapplySeq方法:匹配任意長(zhǎng)度序列

將函數(shù)本身賦予一個(gè)變量:

import math._
val fun = ceil _

匿名函數(shù):

(x: Double) => 3 * x

函數(shù)參數(shù)可以放在大括號(hào)中:

Array(1, 2, 3).map((x: Int) => 3 * x)
Array(1, 2, 3).map{(x: Int) => 3 * x}

函數(shù)接收函數(shù)為參數(shù):

def f(g: (Int) => Int) = g(10)
f((x: Int) => 3 * x)

x的類型可推斷為Int阴汇,因此類型可以省略為:

f((x) => 3 * x)

參數(shù)列表中只有一個(gè)參數(shù)数冬,小括號(hào)可以省略:

f(x => 3 * x)

參數(shù)在=> 右側(cè)僅出現(xiàn)了一次,可以省略為:

f(3 * _) // 簡(jiǎn)寫方式僅能在參數(shù)類型已知的情況下有效

函數(shù)柯里化:

def mulOneAtATime(x: Int)(y: Int) = x * y
mulOneAtATime(3)(4)

柯里化的用途之一:提供更多的類型推斷信息

val a = Array("Hello", "World")
val b = Array("hello", "world")
a.corresponds(b)(_.equalsIgnoreCase(_))

corresponds的定義為:

def corresponds[B](that: Seq[B])(p: (A: B) => Boolean):Boolean

可以根據(jù)第一個(gè)參數(shù)傳進(jìn)去的類型B搀庶,以用于第二個(gè)參數(shù)p

def runInThread(block: () => Unit) = {
  new Thread {
    override def run() {block()}
  }.start()
}
runInThread{() => println("")}

可以將參數(shù)列表省略掉:

def runInThread(block: => Unit) = {
  new Thread {
    override def run() {block} // 調(diào)用時(shí)不需要加括號(hào)
  }.start()
}
runInThread{println("")} // 傳遞匿名函數(shù)時(shí)不需要參數(shù)列表

不可變序列:
Indexed: Vector, Range
non-indexed: List, Stream, Stack, Queue
可變序列:
indexed: ArrayBuffer
non-indexed: Stack, Queue, PriorityQueue, LinkedList, DoubleLinkedList

List包含head和tail
List(9, 4, 2) 相當(dāng)于 9 :: 4 :: 2 :: Nil

集合應(yīng)用的view方法返回的是懶視圖拐纱,只對(duì)被求值的時(shí)候進(jìn)行計(jì)算
可以使用force方法對(duì)懶集合進(jìn)行強(qiáng)制計(jì)算

使用線程安全的集合:混入Synchronized開頭的幾個(gè)集合特質(zhì),例如:

val synchronizedMap = new scala.collection.mutable.HashMap[String, Int] with scala.collection.mutable.SynchronizedMap[String, Int]

集合并行計(jì)算:調(diào)用par函數(shù)

for(i <- (0 until 100).par) print(i + " ")
for(i <- (0 until 100).par) yield i + " "

并行集合轉(zhuǎn)換為串行集合:調(diào)用ser方法

模式匹配:

p match {
  case '+' => ...
  case _: Int => ...
  case e: Exception => e.printStackTrace()
  case _: Int if p % 2 == 0 => ...
  case _ => ... // 相當(dāng)于default
}

match語(yǔ)句也可以是表達(dá)式

for中也可以使用模式:

for((key, "") <- System.getProperties()) {// key為所有值為空白的鍵}

樣例類case class:
樣例類構(gòu)造器每一個(gè)參數(shù)自動(dòng)稱為val哥倔,除非被聲明為var
使用伴生對(duì)象的apply方法創(chuàng)建新對(duì)象
提供unapply方法秸架,可使用模式匹配
生成toString, hasCode, equals和copy方法

copy方法的使用:

case class Person(name: String, age: Int)
val p1 = Person("Paul", 20)
val p2 = p1.copy() // p2為 name="Paul" age=20
val p3 = p1.copy(age=30) // p3 為 name="Paul" age=30

嵌套值綁定到變量:使用@符號(hào)

密封類:
使用樣例類做模式匹配是,編譯器確保已經(jīng)列出了所有可能的選擇
密封類所有的子類都必須在密封類所在的文件中定義

sealed abstract class Direction
case object EAST extends Direction
case object WEST extends Direction
case object NORTH extends Direction
case object SOUTH extends Direction


d match {
  case EAST => ...
  case WEST => ...
  case NORTH => ...
  case SOUTH => ...
}

偏函數(shù):被花括號(hào)包圍的一組case語(yǔ)句為偏函數(shù)咆蒿。

val f: PartialFunction[Char, Int] = {case '+' => 1, case '-' => -1}
f('-') // 調(diào)用f.apply('-') 返回 -1
f.isDefinedAt('0') // false 至少匹配其中一個(gè)模式時(shí)返回true
f('0') // 拋出MatchError

Scala XML

scala內(nèi)建支持XML格式

節(jié)點(diǎn)序列的類型為NodeSeq

var xml = <html><head></head><body></body></html>
for (elem <- xml.child) { // 返回xml的子節(jié)點(diǎn)
  println(elem)
}

可以使用NodeBuffer的形式在程序中構(gòu)建NodeSeq:

var nodeItems = new NodeBuffer
nodeItems += <ul></ul>
var nodes: NodeSeq = nodeItems // NodeSeq為不可變類型东抹,NodeBuffer可以被隱式轉(zhuǎn)換為NodeSeq

通過attributes方法獲取節(jié)點(diǎn)中的屬性:

var node = <img src="image.jpg"></img>
var imgSrc = node.attributes("src") // 結(jié)果為image.jpg沃测,類型為節(jié)點(diǎn)序列,不是字符串
imgSrc.text // 轉(zhuǎn)換類型為字符串
for (attr <- elem.attributes) {} // 遍歷attr.key和attr.value.text

elem.attributes.asAttrMap // 將屬性轉(zhuǎn)換為Map類型

XML內(nèi)嵌表達(dá)式:

var items = Array("Hello", "World")
val elem = <ul><li>{items(0)}</li><li>{items(1)}</li></ul>
println(elem) // 結(jié)果為<ul><li>Hello</li><li>World</li></ul>

XPath匹配XML節(jié)點(diǎn):

val x = elem \ "li" // 返回elem直接所有一級(jí)子節(jié)點(diǎn)為li的節(jié)點(diǎn)
val x = elem \\ "li" // 返回elem所有類型為li的子節(jié)點(diǎn)
val x = elem \ "_" \ "li" // 返回elem所有二級(jí)子節(jié)點(diǎn),且類型為li
val x = elem \ "@src" // 返回elem節(jié)點(diǎn)的src屬性
val x = elem \\ "@src" // 返回elem節(jié)點(diǎn)所有子類節(jié)點(diǎn)的src屬性

從文件中加載XML

import scala.xml.XML
val xmlFile = XML.loadFile("xmlFile.xml")

泛型類
scala使用中括號(hào)表示泛型類:

class Pair[T, S] (val first: T, val second: S)

泛型函數(shù):

class getMiddle[T](arr: Array[T]) = arr(arr.length / 2)
val fun = getMiddle[String] _ //返回一個(gè)函數(shù)惧互,但是類型被限制為String

泛型上界:
[T <: Type] T必須為Type的子類

泛型下界:
[T >: Type] T必須為Type的超類

視圖界定:
[T <% Type] T可以被隱式轉(zhuǎn)換成Type

基本類型數(shù)組泛型指定:需要將上界指定為Manifest

協(xié)變:對(duì)于Pair[+T]喇伯,如果A是B的子類,那么Pair[A]是Pair[B]的子類管宵。
逆變:對(duì)于Pair[+T]箩朴,如果A是B的子類岗喉,那么Pair[A]是Pair[B]的父類。

函數(shù)在參數(shù)上是逆變的炸庞,在返回值上是協(xié)變的钱床。對(duì)于某個(gè)對(duì)象的消費(fèi)適合逆變,而對(duì)于他的產(chǎn)出則適用于協(xié)變埠居。

單例類型:

class A {
  def funA() = {
    ...
    this
  }
}

class B extends A {
  def funB() = {
    ...
    this
  }
}

val b = new B
b.funA.funB // 會(huì)出錯(cuò)查牌,funA返回的this類型為A,A沒有funB方法

將類定義修改為:

class A {
  def funA() = {
    ...
    this.type
  }
}

class B extends A {
  def funB() = {
    ...
    this.type
  }
}
val b = new B
b.funA.funB // 無(wú)問題
object A
class B {
  def funA(obj: A.type) = {} // 指代的是A這個(gè)單例對(duì)象而不是A這個(gè)類型
}

類型別名:

type MyType = HashMap[Int, String]

結(jié)構(gòu)類型:

def fun(obj: {def f(s: String): Any}) {}
// 具有f(s: String): Any方法的類的實(shí)例才能作為該方法的參數(shù)滥壕。(scala使用反射來調(diào)用該方法)

復(fù)合類型:T1 with T2 with T3 ...

自身類型:

trait MyExceptionTrait {
this: Exception =>
...
// this被當(dāng)做Exception對(duì)象來對(duì)待
}

MyExceptionTrait 特質(zhì)只能被混入Exception及其子類中

抽象類型:

trait A{
  type Content
  def make(): Content
}

class B extends A {
  type Content = String // 必須指定類型
  def make():String = {}
}

隱式轉(zhuǎn)換:

package com.paul
class Fraction(val x:Int, val y: Int) {
  def *(another: Fraction) = {...}
}
object Fraction {
  def apply(val x:Int, val y: Int) = new Fraction(x, y)
}

package com.paul
object FractionConversion {
  implicit def int2Fraction(n: Int) = Fraction(n, 1)
}

class Demo extends App {
  import com.paul.FractionConversion._
  val result = 3 * Fraction(3, 2) // 隱式調(diào)用int2Fraction
}

隱式參數(shù):

case class Delimeter(val left: String, val: right: String)

class Tools {
  implicit val delimeter = Delimeter("<<", ">>")
  def makeString(s: String)(implicit delim: Delimeter) = {
    // demimeter會(huì)被隱式的賦予delim
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绎橘,一起剝皮案震驚了整個(gè)濱河市涮较,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌闺属,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匠楚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡与斤,警方通過查閱死者的電腦和手機(jī)撩穿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來食寡,“玉大人雾狈,你說我怎么就攤上這事〉种澹” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)剑鞍。 經(jīng)常有香客問我,道長(zhǎng)光戈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任遂赠,我火速辦了婚禮久妆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跷睦。我一直安慰自己筷弦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布抑诸。 她就那樣靜靜地躺著烂琴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜕乡。 梳的紋絲不亂的頭發(fā)上奸绷,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音层玲,去河邊找鬼号醉。 笑死反症,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的畔派。 我是一名探鬼主播铅碍,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼父虑!你這毒婦竟也來了该酗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤士嚎,失蹤者是張志新(化名)和其女友劉穎呜魄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莱衩,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爵嗅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笨蚁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睹晒。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖括细,靈堂內(nèi)的尸體忽然破棺而出伪很,到底是詐尸還是另有隱情,我是刑警寧澤奋单,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布锉试,位于F島的核電站,受9級(jí)特大地震影響览濒,放射性物質(zhì)發(fā)生泄漏呆盖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一贷笛、第九天 我趴在偏房一處隱蔽的房頂上張望应又。 院中可真熱鬧,春花似錦乏苦、人聲如沸株扛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)洞就。三九已至,卻和暖如春拢驾,著一層夾襖步出監(jiān)牢的瞬間奖磁,已是汗流浹背改基。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工繁疤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咖为,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓稠腊,卻偏偏與公主長(zhǎng)得像躁染,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子架忌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的M掏! 因?yàn)镾cala是基于Java虛擬機(jī)叹放,也就是...
    燈火gg閱讀 3,424評(píng)論 1 24
  • Scala的集合類可以從三個(gè)維度進(jìn)行切分: 可變與不可變集合(Immutable and mutable coll...
    時(shí)待吾閱讀 5,807評(píng)論 0 4
  • 第一章 基礎(chǔ) 聲明和變量 在Scala中饰恕,我們鼓勵(lì)你使用val--除非你真的需要修改它的內(nèi)容。注意:你不需要給出值...
    jackLee閱讀 306評(píng)論 0 0
  • 數(shù)組是一種可變的井仰、可索引的數(shù)據(jù)集合埋嵌。在Scala中用Array[T]的形式來表示Java中的數(shù)組形式 T[]。 v...
    時(shí)待吾閱讀 948評(píng)論 0 0
  • 從去年開始認(rèn)真嘗試畫水彩畫俱恶,一直很喜歡水彩暈染的感覺雹嗦,水彩技法還是挺多的,要畫出更好的效果就得勤練習(xí)合是。畫了一幅...
    趙公子ruby閱讀 228評(píng)論 0 1