-
-
Save xuwei-k/4693037 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package s | |
object Test { | |
// Observe that x.companion is statically typed such that foo is callable | |
def f1() = { | |
val x = new Foo | |
println(x) // Foo instance | |
println(x.companion) // Foo companion | |
println(x.companion.foo) // I'm foo! | |
} | |
// Observe that we now have a static handle on the case class factory | |
def f2() = { | |
val y = Bippy(5) | |
println(y) // Bippy(5) | |
println(y.companion) // Bippy | |
println(y.companion.apply(10)) // Bippy(10) | |
} | |
def f3() = { | |
val y = new Bar | |
/**** | |
println(y.companion) // does not compile | |
b.scala:12: error: Instance of s.Bar has no companion object | |
println(y.companion) | |
^ | |
one error found | |
****/ | |
() | |
} | |
def main(args: Array[String]): Unit = { | |
f1() | |
f2() | |
} | |
} | |
class Foo { | |
override def toString = "Foo instance" | |
} | |
object Foo { | |
def foo = "I'm foo!" | |
override def toString = "Foo companion" | |
} | |
case class Bippy(x: Int) | |
class Bar { | |
override def toString = "Bar instance" | |
} | |
/** No object Bar **/ | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.experimental.macros | |
import scala.language.implicitConversions | |
import scala.reflect.macros.Context | |
package s { | |
object typeOps { | |
def companionImpl[T](c: Context) = { | |
import c.universe._ | |
val CompanionOpsClass = typeOf[CompanionOps[_]].typeSymbol | |
val clazzType = c.prefix.actualType match { | |
case TypeRef(_, CompanionOpsClass, arg :: Nil) => arg | |
case tp => c.abort(c.enclosingPosition, s"Unexpected prefix: $tp/${tp.getClass}") | |
} | |
val companion = clazzType.typeSymbol.companionSymbol match { | |
case NoSymbol => c.abort(c.enclosingPosition, s"Instance of $clazzType has no companion object") | |
case sym => sym | |
} | |
def make[U: c.WeakTypeTag] = c.Expr[U](treeBuild.mkAttributedRef(companion)) | |
make(c.WeakTypeTag(companion.typeSignature)) | |
} | |
} | |
} | |
package object s { | |
implicit class CompanionOps[T](val clazz: T) { | |
def companion: AnyRef = macro typeOps.companionImpl[T] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment