Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala sub type not being accepted

Tags:

scala

I have this class in scala

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

Each subclass of PageComponent has it's own subclass of Page and PageData as well. When a subclass calls page or pageData, I want it to return it's own type for this.

I've tried stuff like

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

and this sort of works such that the subclass can call page and gets the page type defined by implementing the type P.

However, I'm trying to call the initialise method and I'm passing through an object of type Page and it is showing this error

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

I'm obviously wrong here but I thought because P "is a" Page this should work for me.

Any ideas?

-----edit for more info------

I do have something like

class AhoyPage extends Page    

object MyPageComponent extends PageComponent {
  type P = AhoyPage
}

after reading jwinandy's answer I changed the code so that the initialise method is called this way

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

and it now works. So I guess my question is answered. Thanks. That cast isn't very nice though. I have a list of PageInfo that looks like this

PageInfo(page:Page, ...)

when a PageInfo is selected I use the page to look up the page component in a map. There must be a better way of doing it but if not, I'm happy with this.

like image 728
Boomah Avatar asked Dec 18 '25 03:12

Boomah


1 Answers

You have to define P when you subclass.

In you case, you have to had :

type P = com.xxx.gui.Page

Example, this works :

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

}

Please post more of your code if you want to refactor a bit to achieve a better level of composability.

-- edit --

Like https://gist.github.com/3608684

like image 85
jwinandy Avatar answered Dec 20 '25 04:12

jwinandy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!