2017-05-17 57 views
0

我有一幫實用的方法Scala的對象,每個方法使用隱式方法參數s設置隱含的實例變量Scala的對象

object MyObject { 
def a(implicit s:String) = ??? 
def b(implicit s:String) = ??? 
def c(implicit s:String) = ??? 
} 

我不喜歡這樣的事實,我需要的這個implicit s:String在每個參數列表中。有沒有辦法只設置一次變量s(即當第一次訪問對象時)。對於班級,我會做這樣的事情:

class MyClass(implicit s:String) { 
def a() = ??? 
def b() = ??? 
def c() = ??? 
} 

回答

5

簡短的回答是「不,你不能」。

爲什麼?因爲s不是變量,所以它是一個參數。所以它不會在運行時的某個時間點(例如,在第一次加入時)設置,但在編譯時解析(因爲它是隱式的)。

當您在部分代碼中編寫MyObject.a時,編譯器將檢查在當前範圍內是否存在隱式的String定義,並將該定義用於s

如果您在代碼的另一部分使用a,它將使用該範圍中的隱式定義,這可能會有所不同。

所有這些都是在編譯時驗證的,所以它與運行時訪問方法的時間無關(儘管訪問它們可能會改變s的運行時值,如果您有可變隱含,應該避免)。

如果您始終想要爲s使用相同的定義,爲什麼不簡單地將此定義放入對象中?或導入它作爲一個隱含的:

object MyObject { 
    implicit def myImplicitString: String = ??? //first possibility 
    import MyImplicits.stringImplicit //second possibility, if stringImplicit is indeed defined as implicit 
} 

底線是,如果你不想通過隱含的參數,你需要把它的範圍,因爲你的範圍是object,它必須永遠都是一樣的。

但是,使用class有什麼問題?它給你你想要的(避免重複隱式參數)而不改變你的呼叫(如果你將它定義爲case class,只需使用new MyClass().a而不是MyObject.a,或者甚至使用MyCaseClass().a)。如果您的對象中有其他字段,則始終可以將它們放入您的類的伴隨對象中,以儘量減少實例化時的開銷。