Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend ImageView in an Android-Scala app?

I have tried many solutions found in google by the keywords: multiple constructors, scala, inheritance, subclasses.

None seems to work for this occasion. ImageView has three constructors:

ImageView(context)
ImageView(context,attribute set)
ImageView(context,attribute set, style)

In scala you can only extend one of them. And the solution of using the more complete constructor (ImageView(context,attribute set, style)) and passing default values does not work either because the constructor ImageView(context) does something completely different than the other two constructors.

Some solutions of using a trait or a companion object does not seem to work because the CustomView must be a class! I mean I am not the only one who uses this class (so I could write the scala code any way I wanted) there is also the android-sdk who uses this class and yes it must be a class.

target is to have a CustomView which extends ImageView and all of these work:

new CustomView(context)
new CustomView(context,attribute set)
new CustomView(context,attribute set, style)

Please let me know if you need any further clarification on this tricky matter!

like image 921
George Pligoropoulos Avatar asked Dec 11 '12 16:12

George Pligoropoulos


2 Answers

According to Martin Odersky (the creator of Scala), that is not possible.

In http://scala-programming-language.1934581.n4.nabble.com/scala-calling-different-super-constructors-td1994456.html:

"is there a way to call different super-constructors within different class-constructors - or does all have to go up to the main-constructor and only one super-constructor is supported?

No, it has to go through the main constructor. That's one detail where Scala is more restrictive than Java."

I think your best approach is to implement your views in Java.

like image 122
Rui Gonçalves Avatar answered Nov 04 '22 19:11

Rui Gonçalves


It sounds like you may just be better off writing the subclass in Java. Otherwise, if your assumption about the SDK using the three argument constructor is correct, then you could use a trait and a class with a companion object. The SDK would use the three argument constructor of CustomView which also implements a trait containing any additional behavior you need:

trait TCustomView {
  // additional behavior here
}

final class CustomView(context: Context, attributes: AttributeSet, style: Int)
  extends ImageView(context, attributes, style) with TCustomView

In the application code, you could use the one, two or three argument version in this way:

object CustomView {
  def apply(c: Context, a: AttributeSet, s: Int) =
    new ImageView(c, a, s) with TCustomView
  def apply(context: Context, attributes: AttributeSet) =
    new ImageView(context, attributes) with TCustomView
  def apply(context: Context) = new ImageView(context) with TCustomView
}

CustomView(context)
CustomView(context, attributes)
CustomView(context, attributes, style)

Seems like a lot of work. Depending on your goals, you might be able to add additional behavior with implicits:

implicit def imageViewToCustomView(view: ImageView) = new {
  def foo = ...
}
like image 5
yakshaver Avatar answered Nov 04 '22 20:11

yakshaver