物件導向的世界中, 需要有個方法來幫物件做分類管理, 區分功能性並建立架構, package 的概念很熟悉, 它也正是一個物件, 是用來定義複數物件的集合, JAVA的package很基本, 但缺乏彈性, 已知道的比如C#就有scope的package架構, 在Scala中更是講這兩者結合, 端看軟體需求, 讓使用者更方便建立物件
Package
直接來看一個Scala用scope模式來定義package
package com {
package scalapackage {
package first {
class Person(val name:String, val age:Int) {
if( name.length <= 0)
print("need name!!")
def this() = this("TOM", 18)
}
}
}
}
上述的code 就是把Person class定義在com.scalapackage.first package中, scope 的方法看起來很直覺; 或者你也可以用JAVA的方式
package com.scalapackage.first
class Person(val name:String, val age:Int) {
if( name.length <= 0)
print("need name!!")
def this() = this("TOM", 18)
}
或者在最外層加上大括號, 成一個scope package com.scalapackage.first {
class Person(val name:String, val age:Int) {
if( name.length <= 0)
print("need name!!")
def this() = this("TOM", 18)
}
}
這是風格上的差別, scope的方法可以讓你很明確的布局class的架構, 不過當你在同一個Scala檔放入多重pacakge時候, 就有可能第一眼會混淆, 一般來說普遍還是用JAVA的傳統方式在 code file第一行定義好package架構
另一個你該注意的點是, Scala中的package的宣告可以不必和實際上的Filesystem的Folder structure一致, 可以很自由的在同一個scala file中多重宣告package:
另一個你該注意的點是, Scala中的package的宣告可以不必和實際上的Filesystem的Folder structure一致, 可以很自由的在同一個scala file中多重宣告package:
package com.scalapackage {
package first {
class Person
}
package second {
class Animal
}
package third {
class Mental
}
}
把上述的code存在一個package.scala file, 然後用scalac 去compile它, 你可以發現scala compiler會自動幫你生成相對應的 Folder structure, 來確保符合JVM需求
Import
基本上Scala中的import keyword跟JAVA 很類似, 但在JAVA之外又加了很多彈性的應用
再者Scala Program是自動import scala package, 因此你可以直接import util.Random, 不必再加上scala
在Scala中 import 一個package, 在它底下的成員還有subpackage也會都 import進來
import package下的所有class用 底線 "_"
import com.scalapackage._
import 可以用在code file中任何位置
scala> val randomValue = { import scala.util.Random
new Random().nextInt
}
randomValue: Int = 1453905449
上述例子中是在code block 中import Random, 因此你也該明白它的 lexically scoped應該也只限制在該code block中, 以外地方是不知道有Random的!!再者Scala Program是自動import scala package, 因此你可以直接import util.Random, 不必再加上scala
scala> val randomValue = { import util.Random
new Random().nextInt
}
randomValue: Int = 619602925
在Scala中 import 一個package, 在它底下的成員還有subpackage也會都 import進來
要import class的成員, 要加上底線 _ 在class之後
scala> import java.lang.System._
import java.lang.System._
scala> nanoTime
res0: Long = 1268518636387441000
上述code可以直接call nanoTime method 就是因為你import java.lang.System._ 把System的member都拉進來, 這跟JAVA的static import很類似(但你該知道Scala是沒有static)
import name mapping
在Scala中當你在import該class時候, 可以定義一個新的名字去mapping 你所import 的class
這是Scala import中最重要的Feature, 當你可以控制import進來的class name, 大大的增加code的可讀性, 尤其當import namespace conflict
在JAVA中最常見的例子是 java.sql.Date 與 java.util.Date的名稱衝突問題, 你怎知道你同時import兩者時用的是誰的Date? 在Scala中你可以很簡單的解決:
透過大括號, 把sql的Date 名稱轉換成 SqlDate, 後者call Date會很明白是屬於 util package的. 如此減少class 名稱的混淆, 更進一步的, 你還可以hide 已經 import的class, 避免造成衝突:
下一章
這是Scala import中最重要的Feature, 當你可以控制import進來的class name, 大大的增加code的可讀性, 尤其當import namespace conflict
在JAVA中最常見的例子是 java.sql.Date 與 java.util.Date的名稱衝突問題, 你怎知道你同時import兩者時用的是誰的Date? 在Scala中你可以很簡單的解決:
import java.util.Date
import java.sql.{Date => SqlDate}
import RichConsole._
val now = new Date
p(now)
val sqlDate = new SqlDate(now.getTime)
p(sqlDate)
透過大括號, 把sql的Date 名稱轉換成 SqlDate, 後者call Date會很明白是屬於 util package的. 如此減少class 名稱的混淆, 更進一步的, 你還可以hide 已經 import的class, 避免造成衝突:
import java.sql.{Date => _ }
如此一來, sql package的Date就不會被看見了, 你只會call 到 util Date下一章
沒有留言:
張貼留言