3

我在斯卡拉有这门课

trait PageComponent {
  protected var page:Page = _
  protected var pageData:PageData = _
  def initialise(page0:Page, pageData0:PageData) {
    page = page0
    pageData = pageData0    
  }
}

PageComponent 的每个子类也都有自己的 Page 和 PageData 子类。当子类调用 page 或 pageData 时,我希望它为此返回它自己的类型。

我试过像

trait PageComponent {
  type P <: Page
  protected var page:P = _
  protected var pageData:PageData = _
  def initialise(page0:P, pageData0:PageData) {
    page = page0
    pageData = pageData0    
  }
}

这种工作使得子类可以调用 page 并获取通过实现类型 P 定义的页面类型。

但是,我正在尝试调用 initialise 方法,并且正在传递 Page 类型的对象,它显示了此错误

error: type mismatch;
found   : pageInfoToGoTo.page.type (with underlying type com.xxx.gui.Page)
required: pageComponentToGoTo.P
pageComponentToGoTo.initialise(pageInfoToGoTo.page, pageData)

我在这里显然错了,但我认为因为 P“是一个”页面这应该对我有用。

有任何想法吗?

------编辑以获取更多信息-----

我确实有类似的东西

class AhoyPage extends Page    

object MyPageComponent extends PageComponent {
  type P = AhoyPage
}

阅读 jwinandy 的答案后,我更改了代码,以便以这种方式调用初始化方法

pageComponentToGoTo.initialise(pageInfoToGoTo.page.asInstanceOf[pageComponentToGoTo.P], pageData)

现在它可以工作了。所以我想我的问题得到了回答。谢谢。不过这个演员阵容不是很好。我有一个看起来像这样的 PageInfo 列表

PageInfo(page:Page, ...)

选择PageInfo时,我使用该页面查找地图中的页面组件。必须有更好的方法,但如果没有,我对此很满意。

4

2 回答 2

2

子类化时必须定义 P 。

在您的情况下,您必须:

type P = com.xxx.gui.Page

例如,这有效:

trait Page
trait PageData

trait PageComponent {
  type P <: Page
  protected var page:P = _
  protected var pageData:PageData = _
  def initialise(page0:P, pageData0:PageData) {
    page = page0
    pageData = pageData0    
  }
}

class AhoyPage extends Page    

object MyPageComponent extends PageComponent {

    type P = AhoyPage
}

object MyApp extends App {
    MyPageComponent.initialise(new AhoyPage, new PageData {})
    // OR
    MyPageComponent.initialise(new MyPageComponent.P, new PageData {})

}

如果您想稍微重构一下以实现更好的可组合性,请发布更多代码。

- 编辑 -

喜欢https://gist.github.com/3608684

于 2012-09-02T10:33:50.803 回答
0

好吧,问题是这个假设:

我以为因为P“是”页面

你没有声明那P是一个Page. 这就是你声明的:

type P <: Page

这意味着P是 的子类型。目前还不知道子类型是什么,事实上,除非您在某个时候声明等于某物Page,否则您将永远无法传递任何东西。initialiseP

问题是,你真的需要P <: Page吗?你不能只说initialisetake a Page,它包括所有Page的子类型吗?

于 2012-09-02T21:16:23.017 回答