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?
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() );
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With