在工厂中使用特征
我目前正在探索 scala,我想知道是否可以在工厂中使用特征。
我尝试了这个:
abstract class Foo { ... } object Foo { def apply() = new Bar private class Bar extends Foo { ... } } Foo() with MyTrait // Not working
我想这是因为 with
前面必须有 new
。
那么有什么办法可以做到这一点吗?
谢谢
I'm currently discovering scala and I was wondering if I could use traits with a factory.
I tried this :
abstract class Foo { ... } object Foo { def apply() = new Bar private class Bar extends Foo { ... } } Foo() with MyTrait // Not working
I guess it's because with
must be preceded by new
.
So is there any way to do this ?
Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,已经太晚了,当 apply() 方法返回时实例已经创建了。
您可以做的是使用工厂方法内的特征。下面的代码来自我正在编写的一个相当大的代码示例:
在这段代码中,你的头像的类型(职业和种族)是在工厂中根据 RaceType 和 CharacterType 枚举决定的。您拥有的是用于各种不同类型或类型组合的一个工厂。
No it is too late, the instance is already created when the apply() method returns.
What you can do is using the traits inside the factory method. The code below is from a rather big code example I am writing:
In this code the type (profession and race) of your Avatar is decided in the factory based on the RaceType and CharacterType enumerations. What you have is one factory for all sorts of different types or type combinations.
假设你有:
那么:
类似于:
这意味着某种基于原型的继承,而 Scala 没有。 (据我所知。)
(我猜思维中的错误是直观地将 = 符号误认为是“替换符号”。即,因为 Foo() 意味着 Foo.apply() 并且“等于” new Foo,所以你可以用 new Foo 代替 Foo() ,但显然不能。)
Say you have:
Then:
would be analogous to:
which would imply some kind of prototype-based inheritance, which Scala doesn't have. (As far as I know.)
(I'd guess the error in thinking is intuitively mistaking the = sign for a "substitution sign". I.e. since Foo() means Foo.apply() and which "equals" new Foo, you can substitue Foo() with new Foo. Which obviously you can't.)
隐式转换解决方案
Ken 建议代理可以在这种情况下为我们提供帮助。我们在这里尝试做的是在创建实例后向其添加特征。如果其他人编写了该类(以及
apply()
方法)并且您无法访问源代码,则这种“猴子修补”可能会很有用。在这种情况下,您可以通过隐式转换在实例顶部添加代理/包装器(无需手动转换):使用
Foo
示例,我们可以这样做:输出:
我的原因不喜欢这个例子的是:
Baz
不以任何方式使用Foo
。很难看出为什么我们要将usefulMethod()
附加到Foo
。所以我做了一个新的例子,其中我们“实例中的“monkey patch”实际上使用了该实例:
打印:
在此示例中,添加的
Elf
特征使用其扩展的实例的getName
方法。如果您看到任何错误,我将不胜感激,我还不擅长隐式。
Solution with implicit conversion
Ken suggested that a proxy could help us in this case. What we are trying to do here is to add a trait to the instance after it is created. This "monkey patching" could be useful if someone else wrote the class (and the
apply()
method) and you cannot access the source. In this case you can do is add a proxy/wrapper on top of the instance by implicit conversion (no manual conversion needed):Using the
Foo
example we could do this like this:Outputs:
The reason I do not like this example is:
Baz
doesn't useFoo
in any way. It is hard to see the reason why we would want to attach theusefulMethod()
toFoo
.So I made a new example where the the trait we "monkey patch" into the instance actually uses the instance:
Prints:
In this example the added
Elf
trait use thegetName
method of the instance it extends.Would be grateful if you see any errors, I am not the good at implicits (yet).
使用代理和隐式转换的解决方案
此示例扩展了 olle 的解决方案,允许用户在调用
apply()
方法时指定 mixin 特征(例如val xerxes = Avatar [精灵](“薛西斯”)
)。印刷:
Solution with proxies and implicit conversion
This example extends olle's solution to allow the user to specify the mixin trait when calling the
apply()
method (e.g.val xerxes = Avatar[Elf]("Xerxes")
).Prints: