2017-09-26 5 views
1

渡されたジェネリックに基づいてオブジェクトの実装を選択する必要があります。ここに私が望むものの小さな例があります実行時にオブジェクトを選択する方法 - Scala

import scala.reflect.runtime.universe.{TypeTag,typeOf} 


trait Animal27 
{ 
    val name: String 
    val sound: String 
} 


case class Tiger27(name:String, sound: String) extends Animal27 


object Tiger27 
{ 
def AbilityEvolve(tiger27 : Tiger27) : String = 
{ 
    tiger27.name + " is a tigher and she has increased attack" 
} 
} 


case class Cheetah27(name:String,sound:String) extends Animal27 

object Cheetah27 
{ 
    def AbilityEvolve(cheetah27: Cheetah27): String = 
    { 
    cheetah27.name + "is a cheethah and he has increased speed" 
    } 
} 



class World[A: TypeTag] { 

    def getMyObject = 
    { 
    if (typeOf[A] =:= typeOf[Cheetah27]) 
     Cheetah27 
    else 
     Tiger27 
    } 


    def Evolve : String = 
    { 
    getMyObject.AbilityEvolve + " hence evolved" // how do i perform 
                        //getMyObject.AbilityEvolve 
    } 
} 

object App27 extends App{ 
    val world = new World[Cheetah27] 
    println(world.Evolve) 
} 

使用されているジェネリックに基づいてオブジェクトを動的に選択する方法を知っているかもしれません。これは、getMyObject.AbilityEvolveがそれぞれのオブジェクトのメソッドを呼び出すことができるかどうかを確認する方法です。理想的なソリューションが可能戻り値の型のすべてを作ることであろう

答えて

2

おかげで、いくつかの共通の特徴を継承します。したがって、両方ともfooメソッドを持つFirstObjectSecondObjectの間で選択する必要がある場合は、HasFooの特性を定義し、その特性に両方のオブジェクトを混在させます。

trait HasFoo { 
    def foo(): Unit 
} 

object FirstObject extends HasFoo { 
    def foo() = { println("FirstObject") } 
} 

object SecondObject extends HasFoo { 
    def foo() = { println("SecondObject") } 
} 

object WithTraits { 

    def decideAtRuntime(x: Boolean): HasFoo = 
    if (x) FirstObject else SecondObject 

} 

これは効果的です。 JVMランタイムは、このような多態性を行うように構築されており、読者にも明らかです。返されるオブジェクトを制御できない場合は、常にimplicitsを使用して新しい特性のサポートを追加することができます。

しかし、おそらくあなたの戻り値の型があまりにも一般的である、または他の優秀な状況があります。その場合、別の方法があります。 Scalaは、構造型として知られているものをサポートしています。つまり、fooメソッドを持つすべてのオブジェクトを含むタイプ(ではなく、クラス)を定義することができます。

object FirstObject { 
    def foo() = { println("FirstObject") } 
} 

object SecondObject { 
    def foo() = { println("SecondObject") } 
} 

object WithStructure { 

    def decideAtRuntime(x: Boolean): { def foo(): Unit } = 
    if (x) FirstObject else SecondObject 

} 

戻り値の型はdecideAtRuntimeです。クラス名ではなく、{ def foo(): Unit }です。これは、引数が0で何も返さないメソッドfooを持つオブジェクトの構造型です。

Scalaのコンパイラはコンパイル時にメソッドが実際に存在するかどうかを検証するため、構造型は型が安全です。ただし、それはObjectクラスとリフレクションを使用するJVM命令にコンパイルされます。つまり、Java APIがJava APIとのインタフェースを試みると、Java APIは型保証されない可能性があります。また、リフレクションAPIが動作するため、decideAtRuntimeを呼び出すたびにプログラムが遅くなります。

+0

foo()がそれぞれのオブジェクト/修正されたオブジェクトを返すようにするにはどうすればいいでしょうか?ありがとう。 – BigDataScholar

関連する問題