Geo*_*los 11 inheritance android scala multiple-constructors
我通过关键字在谷歌尝试了许多解决方案:多个构造函数,scala,继承,子类.
似乎没有人适合这个场合.ImageView有三个构造函数:
ImageView(context)
ImageView(context,attribute set)
ImageView(context,attribute set, style)
Run Code Online (Sandbox Code Playgroud)
在scala中,您只能扩展其中一个.使用更完整的构造函数(ImageView(context,attribute set, style))并传递默认值的解决方案也不起作用,因为构造函数ImageView(context)执行的操作与其他两个构造函数完全不同.
使用特征或伴随对象的一些解决方案似乎不起作用,因为CustomView必须是一个类!我的意思是我不是唯一一个使用这个类的人(所以我可以按照我想要的方式编写scala代码)还有使用这个类的android-sdk,是的,它必须是一个类.
target是一个扩展ImageView的CustomView,所有这些工作:
new CustomView(context)
new CustomView(context,attribute set)
new CustomView(context,attribute set, style)
Run Code Online (Sandbox Code Playgroud)
如果您需要进一步澄清这个棘手的问题,请告诉我!
根据Martin Odersky(Scala的创建者)的说法,这是不可能的.
"有没有办法在不同的类构造函数中调用不同的超级构造函数 - 或者是否所有必须转到主构造函数并且只支持一个超级构造函数?
不,它必须通过主构造函数.这是Scala比Java更具限制性的一个细节."
我认为您最好的方法是在Java中实现您的视图.
听起来你可能只是更好地在Java中编写子类.否则,如果您对使用三参数构造函数的SDK的假设是正确的,那么您可以使用特征和具有伴随对象的类.SDK将使用三个参数构造函数CustomView,它还实现了一个包含您需要的任何其他行为的特征:
trait TCustomView {
// additional behavior here
}
final class CustomView(context: Context, attributes: AttributeSet, style: Int)
extends ImageView(context, attributes, style) with TCustomView
Run Code Online (Sandbox Code Playgroud)
在应用程序代码中,您可以使用以下方式使用一个,两个或三个参数版本:
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)
Run Code Online (Sandbox Code Playgroud)
好像很多工作.根据您的目标,您可以使用implicit添加其他行为:
implicit def imageViewToCustomView(view: ImageView) = new {
def foo = ...
}
Run Code Online (Sandbox Code Playgroud)
根据AndroidView文档, View(Context)当从代码构造时使用 和View(Context, AttributeSet)(View(Context, AttributeSet, int)并且自 API 级别 21 开始)当从 XML 扩充View(Context, AttributeSet, int, int)时使用。View
XML 构造函数都只调用同一个构造函数,参数最多的构造函数也是唯一具有实际实现的构造函数,因此我们可以在 Scala 中使用默认参数。另一方面,“代码构造函数”可能有另一种实现,因此最好也从 Scala 实际调用。
下面的实现可能是一个解决方案:
private trait MyViewTrait extends View {
// implementation
}
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0)
extends View(context, attrs, defStyle) with MyViewTrait {}
object MyView {
def apply(context: Context) = new View(context) with MyViewTrait
}
Run Code Online (Sandbox Code Playgroud)
然后可以像这样使用“代码构造函数”:
var myView = MyView(context)
Run Code Online (Sandbox Code Playgroud)
(不是真正的构造函数)。
另一个曾经喜欢:
var myView2 = new MyView(context, attrs)
var myView3 = new MyView(context, attrs, defStyle)
Run Code Online (Sandbox Code Playgroud)
这是 SDK 期望的方式。
类似地,对于 API 级别 21 及更高级别,class可以定义为:
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0, defStyleRes: Int = 0)
extends View(context, attrs, defStyle, defStyleRes) with MyViewTrait {}
Run Code Online (Sandbox Code Playgroud)
第四个构造函数可以像这样使用:
var myView4 = new MyView(context, attrs, defStyle, defStyleRes)
Run Code Online (Sandbox Code Playgroud)
更新:
如果您尝试调用protected中的方法View(例如setMeasuredDimension(int, int)从trait. Java 受保护的方法不能从特征中调用。class解决方法是在和实现中实现访问器object:
private trait MyViewTrait extends View {
protected def setMeasuredDimensionAccessor(w: Int, h: Int): Unit
def callingSetMeasuredDimensionAccessor(): Unit = {
setMeasuredDimensionAccessor(1, 2)
}
}
class MyView(context: Context, attrs: AttributeSet, defStyle: Int = 0)
extends View(context, attrs, defStyle) with MyViewTrait {
override protected def setMeasuredDimensionAccessor(w: Int, h: Int) =
setMeasuredDimension(w, h)
}
object MyView {
def apply(context: Context) = new View(context) with MyViewTrait {
override protected def setMeasuredDimensionAccessor(w: Int, h: Int) =
setMeasuredDimension(w, h)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1219 次 |
| 最近记录: |