Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298908

Instantiate generic case class without "new"

I have a Binary Search Tree implementation that uses an Ordering:

case class Bst[T](rootNode: Node[T]) {

  def this(rootValue: T, o: Ordering[T]) = this(Node(rootValue, o))

  def +=(value: T) = {
    val node: Node[T] = rootNode.withValue(value)
    node match {
      case it if it == rootNode => this
      case _ => new Bst[T](node)
    }
  }
}


case class Node[T](value: T,
                ordering: Ordering[T],
                    left: Option[Node[T]] = None,
                   right: Option[Node[T]] = None) {

  def withValue(v: T): Node[T] = {
    ordering.compare(v, value) match {
      case comp if comp < 0 =>
        Node(value, ordering, node(left, v), right)
      case comp if comp > 0 =>
        Node(value, ordering, left, node(right, v))
      case _ => this
    }
  }

  private def node(ref: Option[Node[T]], v: T): Option[Node[T]] = {
    ref.map(_.withValue(v)) orElse Some(Node(v, ordering))
  }
}

It works fine if I call it using new and with an explicit Ordering:

object Tester {
  def main(args: Array[String]) {
    val bst = new Bst[Int](12, Ordering.Int) += 4 += 115 += 19 += 333
  }
}

But I'd like to initialize it without new and preferably also without the explicit Ordering. But I'd like the class to still support different generic types. What do I need to do?

Upvotes: 0

Views: 270

Answers (1)

Eastsun
Eastsun

Reputation: 18859

You can define an explicit companion object for Bst:

object Bst {
  def apply[T](rootValue: T, o: Ordering[T]) = new Bst(rootValue, o)
}

And then you can use Bst(1, Ordering.Int) to create a Bst instance.

scala> Bst(12, Ordering.Int) += 4 += 115
res0: Bst[Int] = Bst(Node(12,scala.math.Ordering$Int$@42c2b246,Some(Node(4,scala.math.Ordering$Int$@42c2b246,None,None)),Some(Node(115,scala.math.Ordering$Int$@42c2b246,None,None))))

If you want to create object without explicit Ordering, you can define as:

object Bst {
  def apply[T: Ordering](rootValue: T) = new Bst(rootValue, implicitly[Ordering[T]])
}

Then:

scala> Bst(1)
res1: Bst[Int] = Bst(Node(1,scala.math.Ordering$Int$@42c2b246,None,None))

Upvotes: 4

Related Questions