Object extends Trait, Class extends Trait, 都必须实现方法
Object extends Trait, Class extends Trait, both have to implement method
我有以下设置:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
现在你可能想知道我为什么要这样做,为什么我让 class 扩展特征。
问题是,在程序的某处有一个 A 的集合。
所以某处:
private val aList: ListBuffer[A] = new ListBuffer[A]
在那里,我还必须放入 Bs(在其他衍生物中,即 C 和 D)
所以我不能让 B-class 不扩展它。
由于所有实例的实现都相同,我想使用对象。
但是我确实需要这个对象也是有原因的。因为有一个class:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
此处返回 B 的 singleton/object。这是在 Worker 中执行 do() 所必需的。
总结一下:
对象 B 是必需的,因为 do() (Worker-Class) 中的通用实现以及 doSomething() 永远不会改变。
class B 是必需的,因为在 BaseType A 的集合中有不同作者的 B 的不同实例。
由于上述原因,对象和 class 都必须实现该特征,所以我在这里陷入了一种进退两难的境地。我找不到看起来更整洁的令人满意的解决方案。
所以,我的问题是(事实证明,作为一个非母语人士,我应该更清楚地说明这一点)
有什么方法可以让 class 扩展特征(或 class)并说明应该在对象中而不是 [=70= 中查找任何抽象方法实现],以便我只能(在对象中)实现一次 "doSomething()"(来自特征)?正如我所说,特质在这里完成了两个不同的任务。
一个是 BaseType,以便集合可以获得 class 的实例。另一个是确保每个对象中都存在 doSomething() 方法的合同。
所以对象 B 需要 扩展特征,因为特征就像一个 Java 接口和每个(!)对象 B(或 C,或 D ) 需要 拥有该方法。 (所以我看到的唯一选项 -> 定义一个 interface/trait 并确保该方法存在)
编辑:以防万一有人想知道。我是如何真正解决问题的:我实现了两个特征。
现在,对于一个 class(在我需要的地方),我扩展两个,而对于另一个,我只扩展一个。所以我实际上从来不需要实现任何不是绝对必要的方法:)
正如我在评论部分所写,我真的不清楚你在问什么。
但是,查看您的代码示例,在我看来 trait A
并不是真正需要的。
您可以使用 Scala SDK 自带的类型:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
或者,作为变体:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
在第一种情况下,您可以使用 B
访问单例实例,在第二种情况下使用 B.aType
。
在第二种情况下,不需要显式声明 apply
方法。
选择你喜欢的。
基本信息是:如果您只定义一个简单的方法,则不需要特性。
这就是 Scala 函数的用途。
列表类型可能如下所示:
private val aList:ListBuffer[()=>Unit] = ???
(顺便说一句:为什么不将其声明为 Seq[()=>Unit]
?它是 ListBuffer
而不是其他类型的序列对调用者来说很重要吗?)
你的员工可能看起来像这样:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
请注意,现在 Worker
类型已变为 class,它提供了调用函数的方法。
所以,真的没有必要Worker
class。
您可以直接获取函数 (aType
) 并调用它,就这样。
如果您总是想调用 object B
中的实现,那么 - 那就那样做吧。
无需将调用包装在其他类型的实例中。
您的示例 class B
只是将调用转发给 B
对象,这确实是不必要的。
甚至不需要创建 B
的实例。
它确实有私有成员变量 creator
,但由于从未使用过,因此永远不会以任何方式访问它。
所以,我建议完全删除 class B
。
您所需要的只是类型 ()=>Unit
,这正是您所需要的:一个不带参数且 returns 什么都没有的函数。
如果你厌倦了一直写()=>Unit
,你可以定义一个类型别名,例如在包对象中。
这是我的建议:
type SideEffect = ()=>Unit
然后你可以使用SideEffect
作为()=>Unit
的别名。
我只能做到这些。
在我看来,这可能不是您想要的。
但也许这会对你有所帮助。
如果你想有一个更具体的答案,如果你能把问题弄清楚就好了。
object B
除了一些特殊规则外,与 class B
并没有太大关系。
如果您希望重用 doSomething
方法,您应该重用对象的实现:
class B {
def doSomething() = B.doSomething()
}
如果要将 object B
指定为 class B
的特定实例,则应执行以下操作:
object B extends B("some particular creator") {
...
}
您也不需要 override
修饰符,尽管它们可以方便地进行编译器检查。
伴随对象 扩展特征的概念对于定义与 class 本身相关的行为(例如静态方法)很有用,而不是 class。换句话说,它允许您的静态方法实现接口。这是一个例子:
import java.nio.ByteBuffer
// a trait to be implemented by the companion object of a class
// to convey the fixed size of any instance of that class
trait Sized { def size: Int }
// create a buffer based on the size information provided by the
// companion object
def createBuffer(sized: Sized): ByteBuffer = ByteBuffer.allocate(sized.size)
class MyClass(x: Long) {
def writeTo(buffer: ByteBuffer) { buffer.putLong(x) }
}
object MyClass extends Sized {
def size = java.lang.Long.SIZE / java.lang.Byte.SIZE
}
// create a buffer with correct sizing for MyClass whose companion
// object implements Sized. Note that we don't need an instance
// of MyClass to obtain sizing information.
val buf = createBuffer(MyClass)
// write an instance of MyClass to the buffer.
val c = new MyClass(42)
c.writeTo(buf)
我有以下设置:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
现在你可能想知道我为什么要这样做,为什么我让 class 扩展特征。
问题是,在程序的某处有一个 A 的集合。 所以某处:
private val aList: ListBuffer[A] = new ListBuffer[A]
在那里,我还必须放入 Bs(在其他衍生物中,即 C 和 D)
所以我不能让 B-class 不扩展它。
由于所有实例的实现都相同,我想使用对象。
但是我确实需要这个对象也是有原因的。因为有一个class:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
此处返回 B 的 singleton/object。这是在 Worker 中执行 do() 所必需的。
总结一下:
对象 B 是必需的,因为 do() (Worker-Class) 中的通用实现以及 doSomething() 永远不会改变。
class B 是必需的,因为在 BaseType A 的集合中有不同作者的 B 的不同实例。
由于上述原因,对象和 class 都必须实现该特征,所以我在这里陷入了一种进退两难的境地。我找不到看起来更整洁的令人满意的解决方案。
所以,我的问题是(事实证明,作为一个非母语人士,我应该更清楚地说明这一点)
有什么方法可以让 class 扩展特征(或 class)并说明应该在对象中而不是 [=70= 中查找任何抽象方法实现],以便我只能(在对象中)实现一次 "doSomething()"(来自特征)?正如我所说,特质在这里完成了两个不同的任务。 一个是 BaseType,以便集合可以获得 class 的实例。另一个是确保每个对象中都存在 doSomething() 方法的合同。
所以对象 B 需要 扩展特征,因为特征就像一个 Java 接口和每个(!)对象 B(或 C,或 D ) 需要 拥有该方法。 (所以我看到的唯一选项 -> 定义一个 interface/trait 并确保该方法存在)
编辑:以防万一有人想知道。我是如何真正解决问题的:我实现了两个特征。
现在,对于一个 class(在我需要的地方),我扩展两个,而对于另一个,我只扩展一个。所以我实际上从来不需要实现任何不是绝对必要的方法:)
正如我在评论部分所写,我真的不清楚你在问什么。
但是,查看您的代码示例,在我看来 trait A
并不是真正需要的。
您可以使用 Scala SDK 自带的类型:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
或者,作为变体:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
在第一种情况下,您可以使用 B
访问单例实例,在第二种情况下使用 B.aType
。
在第二种情况下,不需要显式声明 apply
方法。
选择你喜欢的。 基本信息是:如果您只定义一个简单的方法,则不需要特性。 这就是 Scala 函数的用途。
列表类型可能如下所示:
private val aList:ListBuffer[()=>Unit] = ???
(顺便说一句:为什么不将其声明为 Seq[()=>Unit]
?它是 ListBuffer
而不是其他类型的序列对调用者来说很重要吗?)
你的员工可能看起来像这样:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
请注意,现在 Worker
类型已变为 class,它提供了调用函数的方法。
所以,真的没有必要Worker
class。
您可以直接获取函数 (aType
) 并调用它,就这样。
如果您总是想调用 object B
中的实现,那么 - 那就那样做吧。
无需将调用包装在其他类型的实例中。
您的示例 class B
只是将调用转发给 B
对象,这确实是不必要的。
甚至不需要创建 B
的实例。
它确实有私有成员变量 creator
,但由于从未使用过,因此永远不会以任何方式访问它。
所以,我建议完全删除 class B
。
您所需要的只是类型 ()=>Unit
,这正是您所需要的:一个不带参数且 returns 什么都没有的函数。
如果你厌倦了一直写()=>Unit
,你可以定义一个类型别名,例如在包对象中。
这是我的建议:
type SideEffect = ()=>Unit
然后你可以使用SideEffect
作为()=>Unit
的别名。
我只能做到这些。 在我看来,这可能不是您想要的。 但也许这会对你有所帮助。 如果你想有一个更具体的答案,如果你能把问题弄清楚就好了。
object B
除了一些特殊规则外,与 class B
并没有太大关系。
如果您希望重用 doSomething
方法,您应该重用对象的实现:
class B {
def doSomething() = B.doSomething()
}
如果要将 object B
指定为 class B
的特定实例,则应执行以下操作:
object B extends B("some particular creator") {
...
}
您也不需要 override
修饰符,尽管它们可以方便地进行编译器检查。
伴随对象 扩展特征的概念对于定义与 class 本身相关的行为(例如静态方法)很有用,而不是 class。换句话说,它允许您的静态方法实现接口。这是一个例子:
import java.nio.ByteBuffer
// a trait to be implemented by the companion object of a class
// to convey the fixed size of any instance of that class
trait Sized { def size: Int }
// create a buffer based on the size information provided by the
// companion object
def createBuffer(sized: Sized): ByteBuffer = ByteBuffer.allocate(sized.size)
class MyClass(x: Long) {
def writeTo(buffer: ByteBuffer) { buffer.putLong(x) }
}
object MyClass extends Sized {
def size = java.lang.Long.SIZE / java.lang.Byte.SIZE
}
// create a buffer with correct sizing for MyClass whose companion
// object implements Sized. Note that we don't need an instance
// of MyClass to obtain sizing information.
val buf = createBuffer(MyClass)
// write an instance of MyClass to the buffer.
val c = new MyClass(42)
c.writeTo(buf)