对象扩展特性,类扩展特性,都必须实现方法 [英] Object extends Trait, Class extends Trait, both have to implement method

查看:101
本文介绍了对象扩展特性,类扩展特性,都必须实现方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下设置:

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
 }
}

现在您可能想知道为什么我什至这样做,为什么还要让班级也扩展特质。

Now you may wonder why I even do this, why I let the class extend the trait as well.

问题是,在程序中某处有一个A的集合。
所以某处:

The problem is, that somewhere in the Program there is a Collection of A. So somewhere:

private val aList: ListBuffer[A] = new ListBuffer[A]

并且在其中,我还必须放入Bs(其他派生类,即C和D)

and in there, I also have to put Bs (among other derivates, namely C and D)

所以我不能只是让B类不扩展它。

So I can't just let the B-class not extend it.

由于所有实例的实现都相同,因此我想要使用对象。

As the implementation is the same for all instances, I want to use an Object.

但是还有一个原因是我真的需要该对象。因为有一个类:

But there is also a reason I really need this Object. Because there is a class:

abstract class Worker
{
 def getAType(): A

 def do(): Unit =
 {
   getAType().doSomething()
 }
}

class WorkerA
{
  def getAType(): A =
  {
    return B
  }
}

此处返回B的单例/对象。

Here the singleton/object of B gets returned. This is needed for the implementation of do() in the Worker.

总结:

To summarize:

之所以需要对象B,是因为do()(Worker-Class)中的泛型实现,而且因为doSomething()从未更改。

The object B is needed because of the generic implementation in do() (Worker-Class) and also because doSomething() never changes.

需要类B,因为在BaseType A的集合中,存在具有不同作者的B的不同实例。

The class B is needed because in the collection of the BaseType A there are different instances of B with different authors.

因为对象和类都具有出于上述原因实现特质,我在这里有点两难。我找不到一个看起来更整洁的令人满意的解决方案。

As both the object and the class have to implement the trait for above reasons I'm in kind of a dilemma here. I couldn't find a satisfying solution that looks neater.

因此,我的问题是(原来是一个非母语的人我应该澄清更多)

So, my question is (It turns out as a non-native-speaker I should've clarified this more)

是否有任何方法可以让类扩展特征(或类)并说应该查找任何抽象方法实现在对象而不是类中,这样我就只能在对象中实现一次 doSomething()(来自特征)?正如我所说,特质在这里完成了两项不同的任务。
一个是BaseType,以便集合可以获取该类的实例。另一个是确保在每个对象中都存在doSomething()方法的合同。

Is there any way to let a class extend a trait (or class) and say that any abstract-method implementation should be looked up in the object instead of the class, so that I must only implement "doSomething()" (from the trait) once (in the object)? As I said, the trait fulfills two different tasks here. One being a BaseType so that the collection can get instances of the class. The other being a contract to ensure the doSomething()-method is there in every object.

因此,对象B 需要来扩展特征,因为特征类似于Java接口,并且每个(!)对象B(或C或D)都需要具有该方法。 (因此,我看到的唯一选项->定义接口/特征并确保该方法在那里)

So the Object B needs to extend the trait, because a trait is like a Java interface and every (!) Object B (or C, or D) needs to have that method. (So the only option I see -> define an interface/trait and make sure the method is there)

编辑:以防万一有人想知道。我如何真正解决问题:我实现了两个特征。

edit: In case anyone wonders. How I really solved the problem: I implemented two traits.

现在,对于一个类(需要的地方),我同时扩展了这两个类,而对于另一个类,我只扩展了一个。因此,我实际上从来不必执行并非绝对必要的任何方法:)

Now for one class (where I need it) I extend both and for the other I only extend one. So I actually never have to implement any method that is not absolutely necessary :)

推荐答案

正如我在评论部分中所写的那样,我真的不清楚你在问什么。
但是,在您的代码示例中,在我看来,特征A 并不是必需的。
您可以使用Scala SDK随附的类型:

As I wrote in the comment section, it's really unclear to me what you're asking. However, looking at your code examples, it seems to me that trait A isn't really required. You can use the types that already come with the Scala SDK:

object B extends (()=>Unit) {
  def apply() { /* implementation */ }
}

或者作为变体:

object B {
  val aType:()=>Unit = {() => /* implementation */ }
}

在第一种情况下,您可以访问单例具有 B 的实例,在第二种情况下具有 B.aType 的实例。
在第二种情况下,不需要显式声明 apply 方法。

In the first case, you can access the singleton instance with B, in the second case with B.aType. In the second case, no explicit declaration of the apply method is needed.

选择所需内容喜欢。
基本信息是:仅定义一种简单方法就不需要特征。
这就是Scala函数的作用。

Pick what you like. The essential message is: You don't need a trait if you just define one simple method. That's what Scala functions are for.

列表类型可能如下:

private val aList:ListBuffer[()=>Unit] = ???

(顺便说一句:为什么不将其声明为 Seq [()= > Unit] ?它对调用方重要吗,它是 ListBuffer 而不是其他某种序列吗?)

(By the way: Why not declare it as Seq[()=>Unit]? Is it important to the caller that it is a ListBuffer and not some other kind of sequence?)

您的工作人员可能看起来像这样:

Your worker might then look like this:

abstract class Worker {
  def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
  def do() {aType()}
}

请注意,现在 Worker 类型已成为提供方法的类调用一个函数。
因此,实际上没有必要使用 Worker 类。
您可以直接采用函数( aType )并调用它,就是这样。

Note that now the Worker type has become a class that offers a method that invokes a function. So, there is really no need to have a Worker class. You can just take the function (aType) directly and invoke it, just so.

如果您总是想在对象B 中调用实现,那么-那就这样做吧。
无需将调用包装在其他类型的实例中。
您的示例类 B 只是将调用转发到 B 对象,这实际上是不必要的。
甚至不需要创建 B 的实例。
它确实具有私有成员变量 creator ,但由于从未使用过,因此绝不会以任何方式对其进行访问。

If you always want to call the implementation in object B, well - just do that then. There is no need to wrap the call in instances of other types. Your example class B just forwards the call to the B object, which is really unnecessary. There is no need to even create an instance of B. It does have the private member variable creator, but since it's never used, it will never be accessed in any way.

因此,我建议完全删除类B
您所需要的只是类型()=> Unit ,这正是您所需要的:一个不带参数且不返回任何内容的函数。

So, I would recommend to completely remove the class B. All you need is the type ()=>Unit, which is exactly what you need: A function that takes no parameters and returns nothing.

如果您一直厌倦编写()=> Unit ,则可以定义类型别名,例如在包对象中。
这是我的建议:

If you get tired of writing ()=>Unit all the time, you can define a type alias, for example inside the package object. Here is my recommentation:

type SideEffect = ()=>Unit

然后,您可以使用 SideEffect 作为( )=>单位

Then you can use SideEffect as an alias for ()=>Unit.

这就是我能做到的。
在我看来,这可能不是您想要的。
但这可能会在整个过程中对您有所帮助。
如果您想有一个更具体的答案,那么请您澄清问题。

That's all I can make of it. It looks to me that this is probably not what you were looking for. But maybe this will help you a little bit along the way. If you want to have a more concrete answer, it would be nice if you would clarify the question.

这篇关于对象扩展特性,类扩展特性,都必须实现方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆