我目前正在發現scala,我在想是否可以在工廠使用特徵。使用工廠特徵
我嘗試這樣做:
abstract class Foo { ... } object Foo { def apply() = new Bar private class Bar extends Foo { ... } } Foo() with MyTrait // Not working
我想這是因爲with
必須new
之前。
那麼有沒有辦法做到這一點?
謝謝
我目前正在發現scala,我在想是否可以在工廠使用特徵。使用工廠特徵
我嘗試這樣做:
abstract class Foo { ... } object Foo { def apply() = new Bar private class Bar extends Foo { ... } } Foo() with MyTrait // Not working
我想這是因爲with
必須new
之前。
那麼有沒有辦法做到這一點?
謝謝
不,它太晚了,apply()方法返回時已創建實例。
你可以做的是使用工廠方法內的特質。下面的代碼是從相當大的代碼示例我寫:
object Avatar {
// Avatar factory method
def apply(name: String, race: RaceType.Value, character: CharacterType.Value
): Avatar = {
race match {
case RaceType.Dwarf => {
character match {
case CharacterType.Thief => new Avatar(name) with Dwarf with Thief
case CharacterType.Warrior => new Avatar(name) with Dwarf with Warrior
case CharacterType.Wizard => new Avatar(name) with Dwarf with Wizard
}
}
case RaceType.Elf => {
character match {
case CharacterType.Thief => new Avatar(name) with Elf with Thief
case CharacterType.Warrior => new Avatar(name) with Elf with Warrior
case CharacterType.Wizard => new Avatar(name) with Elf with Wizard
}
}
}
}
}
class Avatar(val name: String) extends Character {
...
}
在這段代碼中自己的頭像的類型(職業和種族)在基礎上,RaceType和CharacterType枚舉工廠決定。你有什麼是一個工廠爲各種不同類型或類型的組合。
在你的情況下,我們必須提前知道我們可以使用的不同特徵。但是如果我們不這樣做,是否有可能通過'def apply [T]()= new Foo with T'的概念中的定義將這些特性轉化爲工廠方法? – 2010-08-01 11:59:25
@Mr_Qqn:不,你不能通過傳遞清單來做到這一點。如果您需要這種行爲,可以創建代理將代表特定特徵代入工廠創建的對象,併爲創建必要代理的特徵創建(隱式)轉換。 – 2010-08-01 15:39:32
謝謝,它與代理完美配合。但是,通過創建隱式轉換,你的意思是什麼?一個'帶MyTrait的新FooProxy'可以正確完成這項工作。 – 2010-08-01 17:23:31
假設你有:
class Foo
object Foo { def apply() = new Foo }
trait Baz
然後:
Foo() with Baz
就類似於:
val foo = new Foo
foo with Baz
這將意味着某種形式的基於原型的繼承,這斯卡拉沒有按沒有。 (據我所知。)
(我猜想在思考錯誤是直接誤認爲=符號爲「替代符號」。即因爲Foo()意味着Foo.apply()和哪個「等於」新富,你可以用新富substitue富()。很明顯,你可以沒有哪個)
解決方案與隱式轉換
肯建議,代理可以幫助我們在這種情況下。我們在這裏試圖做的是在實例創建之後添加一個特徵。如果其他人編寫了該類(和apply()
方法),並且無法訪問源,則此「猴子修補」可能很有用。在這種情況下,你所能做的就是增加對隱式轉換實例頂部的代理/包裝(無需手動轉換):
使用Foo
例子中,我們可以做到這一點是這樣的:
class Foo
object Foo { def apply() = new Foo }
trait Baz { def usefulMethod(s: String) = "I am really useful, "+ s }
// ---- Proxy/Wrapper ----
class FooWithBazProxy extends Foo with Baz
// --- Implicit conversion ---
implicit def foo2FooWithBazProxy(foo: Foo): FooWithBazProxy = new FooWithBazProxy
// --- Dummy testcode ---
val foo = Foo()
println(foo.usefulMethod("not!"))
輸出:
I am really useful, not!
我不喜歡這個例子的原因是:
Baz
不以任何方式使用Foo
。很難看到我們爲什麼要附上usefulMethod()
到Foo
的原因。
所以我做了其中的特點,我們「猴子補丁」到實例實際使用的情況下一個新的例子:
// --------- Predefined types -----------
trait Race {
def getName: String
}
class Avatar(val name: String) extends Race{
override def getName = name
}
object Avatar{
def apply() = new Avatar("Xerxes")
}
// ---------- Your new trait -----------
trait Elf extends Race {
def whoAmI = "I am "+ getName + ", the Elf. "
}
// ---- Proxy/Wrapper ----
class AvatarElfProxy(override val name: String) extends Avatar(name) with Elf
// ---- Implicit conversion ----
implicit def avatar2AvatarElfProxy(Avatar: Avatar): AvatarElfProxy = new AvatarElfProxy(Avatar.name)
// --- Dummy testcode ---
val xerxes= Avatar()
println(xerxes.whoAmI)
打印:
I am Xerxes, the Elf.
在這個例子中添加的Elf
特徵使用它擴展的實例的getName
方法。
如果您發現任何錯誤,我將不勝感激(尚)。
我擴展了您的解決方案以啓用代碼,如'val xerxes = Avatar [Elf](「Xerxes」)' – 2010-08-03 16:49:07
與代理和隱式轉換
解此示例擴展歐萊的溶液,以允許用戶調用apply()
方法(例如val xerxes = Avatar[Elf]("Xerxes")
)時指定混入性狀。
// ----- Predefined types -----
trait Race {
def whoAmI: String
}
class Avatar[R <: Race](val name: String)
object Avatar {
def apply[R <: Race](name: String) = new Avatar[R](name)
}
// ----- Generic proxy -----
class AvatarProxy[R <: Race](val avatar: Avatar[R])
implicit def proxy2Avatar[R <: Race](proxy: AvatarProxy[R]): Avatar[R] =
proxy.avatar
// ----- A new trait -----
trait Elf extends Race {
self: AvatarProxy[Elf] =>
def whoAmI = "I am " + self.name + ", the Elf."
}
implicit def avatar2Elf(avatar: Avatar[Elf]): AvatarProxy[Elf] with Elf =
new AvatarProxy[Elf](avatar) with Elf
// --- Test code -----
val xerxes = Avatar[Elf]("Xerxes")
println(xerxes.whoAmI)
打印:
我是薛西斯的精靈。
可能的重複[如何在scala中的泛型方法中創建特徵實例?](http://stackoverflow.com/questions/3274279/how-do-i-create-an-instance在一個通用的方法在斯卡拉) – 2010-08-01 15:42:33