2

I am working in ScalaFX Project. In this moment I am adapting classes from javafx.scene.control.cell. In this package, methods with same signature are duplicated in many classes. e.g. StringConverter<T> converter(). To avoid unnecessary duplication of code (and to know how to use existential types), I created the following code:

// Defined in scalafx.util package. All classes in scalafx use this trait
package scalafx.util

trait SFXDelegate[+D <: Object] extends AnyRef {
  def delegate: D

  override def toString = "[SFX]" + delegate.toString

  override def equals(ref: Any): Boolean = {
    ref match {
      case sfxd: SFXDelegate[_] => delegate.equals(sfxd.delegate)
      case _ => delegate.equals(ref)
    }
  }

  override def hashCode = delegate.hashCode
}

// Package Object
package scalafx.scene.control

import javafx.{ util => jfxu }
import javafx.beans.{ property => jfxbp }
import javafx.scene.{ control => jfxsc }
import scalafx.Includes._
import scalafx.beans.property.ObjectProperty
import scalafx.util.SFXDelegate
import scalafx.util.StringConverter

package object cell {

  type Convertable[T] = {
    def converterProperty: jfxbp.ObjectProperty[jfxu.StringConverter[T]]
  }

  type JfxConvertableCell[T] = jfxsc.Cell[T] with Convertable[T]

  trait ConvertableCell[C <: JfxConvertableCell[T], T]
    extends SFXDelegate[C] {
    def converter: ObjectProperty[StringConverter[T]] = ObjectProperty(delegate.converterProperty.getValue)
    def converter_=(v: StringConverter[T]) {
      converter() = v
    }
  }

}

In JfxConvertableCell type I wanna say

My type is a javafx.scene.control.Cell of type T that has a method called converterProperty that returns a javafx.beans.property.ObjectProperty of type javafx.util.StringConverter[T].

While in ConvertableCell trait, my intention is say that delegate value (from SFXDelegate trait) must be of type JfxConvertableCell. The first class that I tried to create was the counter-part of CheckBoxListCell:

package scalafx.scene.control.cell

import javafx.scene.control.{cell => jfxscc}
import scalafx.scene.control.ListCell
import scalafx.util.SFXDelegate

class CheckBoxListCell[T](override val delegate: jfxscc.CheckBoxListCell[T] = new jfxscc.CheckBoxListCell[T])
  extends ListCell[T](delegate)
  with ConvertableCell[jfxscc.CheckBoxListCell[T], T]
  with SFXDelegate[jfxscc.CheckBoxListCell[T]] {

}

However in this moment I got this message from compiler:

type arguments [javafx.scene.control.cell.CheckBoxListCell[T],T] do not conform to trait ConvertableCell's type parameter bounds [C <: scalafx.scene.control.cell.package.JfxConvertableCell[T],T]

Did I understand something wrong? CheckBoxListCell have the converterProperty method. Can't we use types and existential types as a mold into which we fit our delegated classes?

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Rafael Afonso
  • 595
  • 1
  • 10
  • 28
  • i am not shure why it does not work. cant you work with some implicit conversions which cast to the type you want to get? https://gist.github.com/257758 – Alex Sep 10 '12 at 11:31
  • Probably the relation CheckBoxListCell <: JfxConvertableCell is not true because the compiler is not smart enough to see this. – Alex Sep 10 '12 at 11:37

1 Answers1

1

The problem is in your definition of converterProperty. You define it as a parameterless method, while it is seen by scala as a method with an empty parameter list. Just doing this makes it compile properly:

type Convertable[T] = {
  def converterProperty(): jfxbp.ObjectProperty[jfxu.StringConverter[T]]
}

While scala treats a parameterless method and a method with an empty parameter list as essentially the same thing as far as overriding is concerned (see scala spec @ 5.1.4), they are still different entites. And when interroperating with java code (which has no notion of parameterless method), a nullary method is seen as a method with an empty prameter list, not as a parameterless method, thus the structural types don't match.

Régis Jean-Gilles
  • 32,541
  • 5
  • 83
  • 97