我有两个结构等效的类对,唯一的区别是类型。我希望能够将V1
与V2
和K1
与K2
合并。我控制了这四个类,但我无法修改takesDoublesOrLists
- 它来自一个库。
class V1 (
val a: Double,
val b: Double,
// ...
val z: Double
)
class K1(v: V1) {
def doIt = takesDoublesOrLists(v.a, v.b, /* ..., */ v.z)
}
class V2 (
val a: List[Double],
val b: List[Double],
// ...
val z: List[Double]
)
class K2(v: V2) {
def doIt = takesDoublesOrLists(v.a, v.b, /* ..., */ v.z)
}
我尝试关注type class pattern,但收到的错误是重载的方法takesDoublesOrLists
无法应用于我的类型参数。
修改
重载函数takesDoublesOrLists
的签名顾名思义:
def takesDoublesOrLists(a: Double, b: Double, /* ..., */ z: Double): Something = /* ... */
def takesDoublesOrLists(a: List[Double], b: List[Double], /* ..., */ z: List[Double]): Something = /* ... */
答案 0 :(得分:1)
我可以看到您如何合并 public class MainActivity extends Activity {
private ViewPager mViewPager;
MediaPlayer mp;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager= (ViewPager) findViewById(R.id.view_pager);
ImageAdapter adapter = new ImageAdapter(this);
mViewPager.setAdapter(adapter);
final GestureDetector tapGestureDetector = new GestureDetector(this, new TapGestureListener());
mViewPager.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
tapGestureDetector.onTouchEvent(event);
return false;
}
});
}
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mViewPager.getCurrentItem() == 0) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.aa);
mp.start();
}
}
else if (mViewPager.getCurrentItem() == 1) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.bb);
mp.start();
}
}
else if (mViewPager.getCurrentItem() == 2) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.cc);
mp.start();
}
}
else if (mViewPager.getCurrentItem() == 3) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.dd);
mp.start();
}
}
else if (mViewPager.getCurrentItem() == 4) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.ee);
mp.start();
}
} else if (mViewPager.getCurrentItem() == 5) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.ff);
mp.start();
}
}
else if (mViewPager.getCurrentItem() == 6) {
if(mp != null && mp.isPlaying()){
mp.pause();
}else{
mp = MediaPlayer.create(MainActivity.this, R.raw.gg);
mp.start();
}
}
return super.onSingleTapConfirmed(e);
}
}
}
和V1
,但不能合并V2
或K1
:
K2
编辑:如果您的K1和K2类比您举例说明的更复杂,您可以使用特征来打破这种行为:
class V[T] (
val a: T,
val b: T
// ...
val z: T
)
class K1(v: V[Double]) {
def doIt = takesDoublesOrLists(v.a, v.b, /* ..., */ v.z)
}
class K2(v: V[List[Double]]) {
def doIt = takesDoublesOrLists(v.a, v.b, /* ..., */ v.z)
}
答案 1 :(得分:1)
我尝试了类型类模式,但是出现了一个错误,即重载方法takeDoublesOrLists无法应用于我的类型参数。
您没有显示您的尝试,但您不应该调用takesDoublesOrLists
的重载版本,它应该是类型类的一部分(当然,您可以在调用现有版本时调用现有版本实施它,如果有理由不在那里移动实施):
sealed trait DoubleOrList[A] {
def doIt(a: A, b: A, /* ..., */ z: A): Something
}
object DoubleOrList {
implicit object DoubleIsDoubleOrList extends DoubleOrList[Double] {
def doIt(a: Double, b: Double, /* ..., */ z: Double): Something =
SomeObject.takesDoublesOrLists(a, b, z)
}
implicit object ListIsDoubleOrList extends DoubleOrList[List[Double]] {
def doIt(a: List[Double], b: List[Double], /* ..., */ z: List[Double]): Something =
SomeObject.takesDoublesOrLists(a, b, z)
}
}
// this context bound isn't really necessary, but it prevents you from creating V[String] you can't use
class V[A: DoubleOrList](
val a: A,
val b: A,
// ...
val z: A
)
class K[A](v: V[A])(implicit dOrL: DoubleOrList[A]) {
def doIt = dOrL.doIt(v.a, v.b, /* ..., */ v.z)
}