Created
January 17, 2011 22:31
-
-
Save mariogleichmann/783618 to your computer and use it in GitHub Desktop.
'Elvis' Operator with Scala Dynamic Trait
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
object DynamicElvis { | |
class DynamicImpl( x: AnyRef ) extends Dynamic { | |
def _select_(name: String): DynamicElvis = { | |
val mName = name.substring(0, name.length - 1 ) | |
val mVal = x.getClass.getMethod(mName).invoke( x ) | |
new DynamicElvis( if( mVal != null ) Some( mVal ) else None ) | |
} | |
def _invoke_(name: String)(args: Any*) = { | |
error("unsupported") | |
} | |
} | |
trait Elvis extends Dynamic{ | |
def _select_(name: String): DynamicElvis = { | |
val mName = name.substring(0, name.length - 1 ) | |
val mVal = this.getClass.getMethod(mName).invoke( this ) | |
new DynamicElvis( if( mVal != null ) Some( mVal ) else None ) | |
} | |
def _invoke_(name: String)(args: Any*) = { | |
error("unsupported") | |
} | |
} | |
class DynamicElvis( x: Option[AnyRef] ) extends Dynamic { | |
def _select_(name: String): DynamicElvis = { | |
if( name.endsWith( "Q" ) ){ | |
val mName = name.substring( 0, name.length - 1 ) | |
new DynamicElvis( | |
x.flatMap{ cVal => | |
val nVal = cVal.getClass.getMethod(mName).invoke( cVal ) | |
if( nVal != null ) Some( nVal ) else None } ) | |
} | |
else{ | |
error( name + "doesn't end with Q" ) | |
} | |
} | |
def _invoke_(name: String)(args: Any*) = { | |
error("unsupported") | |
} | |
override def typed[T] : T = { | |
x match { | |
case Some( v ) => v.asInstanceOf[T] | |
case _ => null.asInstanceOf[T] | |
} | |
} | |
override def toString = "Dynamic(" + x.toString + ")" | |
} | |
implicit def toDynamic( x :Any ): Dynamic = new DynamicImpl( x.asInstanceOf[AnyRef] ) | |
class Person( adr :Adress ){ | |
def adress = adr | |
} | |
class Adress( c :City ){ | |
def city = c | |
} | |
class City( c :String ){ | |
def code = c | |
} | |
def getCode( p :Dynamic ){ | |
println( p.adressQ.cityQ.codeQ.typed[String] ) | |
} | |
def main( args :Array[String] ){ | |
val p1 = new Person( new Adress( new City( "1111" ) ) ) | |
val p2 = new Person( null ) | |
val p3 = new Person( null ) with Elvis | |
getCode( p1 ) | |
getCode( p2 ) | |
println( p3.adressQ.cityQ.codeQ.typed[String] ) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment