복붙노트

[SCALA] 주어진 제네릭 형식 스칼라에 의해 클래스의 동반자 오브젝트를 취득

SCALA

주어진 제네릭 형식 스칼라에 의해 클래스의 동반자 오브젝트를 취득

내가 뭘하려고 오전 제네릭 클래스를 가지고 그 안에 정적 방법을 사용하는 함수를 만드는 것입니다 (죄송합니다 자바 언어에 대한 자사의 동반자 개체의 I 평균 방법).

trait Worker {def doSth: Unit}

class Base

object Base extends Worker

// this actually wouldn't work, just to show what I'm trying to achieve
def callSthStatic[T that companion object is <: Worker](implicit m: Manifest[T]) {
  // here I want to call T.doSth (on T object)
  m.getMagicallyCompanionObject.doSth
}

어떤 아이디어?

해결법

  1. ==============================

    1.나는이 작업을 수행하는 방법을 잊어 버린 경우이 페이지를 타격 유지하고 대답은 나를 위해하지 백퍼센트 만족. 내가 반사와 어떻게 여기에 있습니다 :

    나는이 작업을 수행하는 방법을 잊어 버린 경우이 페이지를 타격 유지하고 대답은 나를 위해하지 백퍼센트 만족. 내가 반사와 어떻게 여기에 있습니다 :

    val thisClassCompanion = m.reflect(this).symbol.companion.asModule
    val structural = m.reflectModule(thisClassCompanion)
                      .instance.asInstanceOf[{def doSth: Unit}]
    

    당신은 클래스가 실제로 동반자 개체가 있는지 확인해야 할 수도 있습니다 또는 companion.asModule는 반사 예외가 모듈 아니다 발생합니다

    업데이트 : 명확하게하기 위해 또 다른 예를 추가 :

        object CompanionUtil {
    
      import scala.reflect.runtime.{currentMirror => cm}
    
      def companionOf[T, CT](implicit tag: TypeTag[T]): CT = {
        Try[CT] {
          val companionModule = tag.tpe.typeSymbol.companion.asModule
          cm.reflectModule(companionModule).instance.asInstanceOf[CT]
        }
      }.getOrElse(throw new RuntimeException(s"Could not get companion object for type ${tag.tpe}"))
    
    }
    
  2. ==============================

    2.마일 사빈에 의해 요점은 당신에게 힌트를 줄 수 있습니다 :

    마일 사빈에 의해 요점은 당신에게 힌트를 줄 수 있습니다 :

    trait Companion[T] {
      type C
      def apply() : C
    }
    
    object Companion {
      implicit def companion[T](implicit comp : Companion[T]) = comp()
    }
    
    object TestCompanion {
      trait Foo
    
      object Foo {
        def bar = "wibble"
    
        // Per-companion boilerplate for access via implicit resolution
        implicit def companion = new Companion[Foo] {
          type C = Foo.type
          def apply() = Foo
        }
      }
    
      import Companion._
    
      val fc = companion[Foo]  // Type is Foo.type
      val s = fc.bar           // bar is accessible
    }
    

    이는 스칼라 2.9.x.를 사용하여 -Ydependent - 메소드 유형 플래그 경우 컴파일되어야한다

  3. ==============================

    3.당신은 동반자 클래스와 인스턴스를 얻기 위해 반사를 사용할 수 있지만 그 일부까지 (?) 미래에서 변경 될 수 있습니다 스칼라 내부에 의존한다. 당신이 AnyRef를 얻을로 그리고 어떤 종류의 안전이 없습니다. 하지만 당신의 클래스와 객체에 어떤 implicits를 추가 할 필요가 없다.

    당신은 동반자 클래스와 인스턴스를 얻기 위해 반사를 사용할 수 있지만 그 일부까지 (?) 미래에서 변경 될 수 있습니다 스칼라 내부에 의존한다. 당신이 AnyRef를 얻을로 그리고 어떤 종류의 안전이 없습니다. 하지만 당신의 클래스와 객체에 어떤 implicits를 추가 할 필요가 없다.

    def companionOf[T : Manifest] : Option[AnyRef] = try{
      val classOfT = implicitly[Manifest[T]].erasure
      val companionClassName = classOfT.getName + "$"
      val companionClass = Class.forName(companionClassName)
      val moduleField = companionClass.getField("MODULE$")
      Some(moduleField.get(null))
    } catch {
      case e => None
    }
    
    case class A(i : Int)
    
    companionOf[A].collect{case a : A.type  => a(1)}
    // res1: Option[A] = Some(A(1))
    
  4. from https://stackoverflow.com/questions/9172775/get-companion-object-of-class-by-given-generic-type-scala by cc-by-sa and MIT license