Question

I'm attempting to learn Scala so I have decided to implement datastructures with it. I've begun with the Stack. I have created the following Stack class.

class Stack[A : Manifest]() {

  var length:Int = -1
  var data = new Array[A](100)

  /**
   * Returns the size of the Stack.
  * @return the size of the stack
  */
 def size = {length} 

  /**
   * Returns the top element of the Stack without
   * removing it.
   * @return Stacks top element (not removed)
   */
  def peek[A] = {data(length)}

  /**
   * Informs the developer if the Stack is empty.
   * @return returns true if it is empty else false.
   */
  def isEmpty = {if(length==0)true else false}

  /**
   * Pushes the specified element onto the Stack.
   * @param The element to be pushed onto the Stack
   */
  def push(i: A){
    if(length+1 == data.size) reSize
    length+=1
    data(length) = i;
  }

  /**
   * Pops the top element off of the Stack.
   * @return the pop'd element.
   */
  def pop[A] = {
    length-=1
    data(length)
  }

  /**
   * Increases the size of the Stack by 100 indexes.
   */
  private def reSize{
    val oldData = data;
    data = new Array[A](length+101)
    for(i<-0 until length)data(i)=oldData(i)
   }
}

I Then attempt to initialize this class in my Java class using the following

Stack<Integer> stack = new Stack<Integer>();

However, I'm told that the constructor doesn't exist and that I should add an argument to match Manifest. Why does this happen and how can I fix it?

Was it helpful?

Solution

Alexey gave you the correct explanation but it is definitely possible to create manifest in you code (you just need a java.lang.Class object, which you can easily create in Java).

First you should add a java-friendly factory method to the companion object of Stack:

object Stack {
  def ofType[T]( klass: java.lang.Class[T] ) = {
    val manifest =  new Manifest[T] {
      def erasure = klass
    }
    new Stack()(manifest)
  }
}

This method will generated the appropriate manifest (from a java class) and will pass it explicitly to the Stack constructor. You can then use it from Java without pain:

Stack<String> stack = Stack.ofType( String.class );
stack.push( "Hello" );
stack.push( "World" );

System.out.println( stack.size() );
System.out.println( stack.peek() ); 

OTHER TIPS

This happens because a context bound like [A : Manifest] is just a shorthand for an implicit constructor argument. So your class is "really" declared as class Stack[A]()(implicit m: Manifest[A]) {. So since the only way to create a Manifest is compiler magic (as far as I know), you can't do it from Java and can't construct a Stack there.

You can either change the design to avoid manifests, or create instances of Stack in Scala code and only use them from Java.

Follow up on paradigmatic answer, you can also create a constructor for your class:

class Stack[A](implicit m: Manifest[A]) {

def this(clazz : Class[A]) {
  this()(new Manifest[A] {
    def erasure = clazz
  })
}

that can be then called from Java:

Stack<Integer> s = new Stack<Integer>(Integer.class);
s.push(1);
System.out.println(s.peek());

Nevertheless, the problem will be with generic types like having stacks of stacks of strings. For this you should look into this thread: http://www.scala-lang.org/node/7267

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top