0

次のようなコードがあります。

class testClass {
    class A(val next:Option[A]){
        def printA=println("A called")

    }

    class B(val someValue:Int){
        def printB=println("B called with value "+someValue)
    }

    def printStuff[T](obj:T):Any={
        obj match{
        case a:A=>{ a.printA
                    return new A(Some(a))
                    }
        case b:B=>{ b.printB
                    return  if (b.someValue==0) new B(0) else
                        printStuff(new B(b.someValue-1))
                    }
        }
    }

ここでは、メソッドprintStuffで、入力と同じタイプのオブジェクトを返したいと思います。ただし、これをコンパイルしようとすると、次のエラーが発生します。

error: type mismatch;
found   : a.type (with underlying type testClass.this.A)
required: T
return a

の同様のエラーでreturn b。戻り値の型をAnyに設定できることはわかっていますが、「実際の」コードでは、関数を再帰下降方式で適用しているため、かなりの数asInstanceOfのsを追加する必要があります。避ける。

関数を完全に書き直すことなく、Scalaの型システムに私が書き込もうとしているものを理解させることは可能ですか?

編集:実際のコードで重要になる可能性のあるものを引き出すために、例を編集しようとしました:

  • 再帰的であるという事実

  • その戻り型が引数の1つに依存するという事実。

4

2 に答える 2

3

printStuffとにかくこれが事実上あなたがしていることなので、なぜ各引数タイプに対して単純にオーバーロードしないのですか?

def printStuff(a : A) = {a.printA; new A(Some(a))}
def printStuff(b : B) = {b.printB; new B(b.someValue - 1)}

または、抽象化したい一般的な動作があり、単一のメソッドを保持する場合は、型クラスのルートをたどることができます。

trait Cloneable[T] { def clone(t : T) : T }
object Cloneable {
  implicit object AIsCloneable extends Cloneable[A] { def clone(a : A) = new A(Some(a)) }
  implicit object BIsCloneable extends Cloneable[B] { def clone(b : B) : B = if (b.someValue == 0) new B(0) else new B(b.someValue -1) }
}

def printStuff[T : Cloneable](t : T) = implicitly[Cloneable[T]].clone(t)
于 2012-08-14T17:05:47.673 に答える
0

asInstanceOfをリターンに追加できます。それはあなたのプロダクションコードに問題を引き起こしますか?

何かのようなもの:

def printStuff[T](obj:T):T={
    obj match{
      case a:A=>{ a.printA
        a.asInstanceOf[T]
      }
      case b:B=>{ b.printB
        b.asInstanceOf[T]
      }
    }
  }
于 2012-08-14T16:34:51.937 に答える