클래스 객체 사용하기
Java 에서는 클래스 객체를 쓰려면 String.class
같은 식으로 쓴다. Scala는 이 문법을 쓰지 않고 아래처럼 한다.
val cls = classOf[String] ;
타입명을 []안에 쓰게하여 언어의 다른 요소와 일관성을 맞추려 한 것 같다. 하지만 개인적으로는 Java문법이 더 편하다.
캐스팅하기, 특정 타입인지 검사하기
Java에서는 캐스팅할 때 C와 같은 문법을 쓰는데 Scala는 아래처럼 한다.
// 특정 객체를 String 타입으로 캐스팅
val str = someObj.asInstanceOf[String];
캐스팅 문법은 Scala가 더 좋다.
객체가 특정 타입인지 검사할 때 Java는 instanceof
연산자를 쓴다.
if( someObj instanceof Integer ) {
Integer i = (Integer)someObj ;
System.out.println(i*i) ;
}
else {
// Integer가 아닌 경우 처리
}
Scala에는 instanceof
에 해당하는게 없고 패턴매칭을 쓴다.
someObj match {
case i:Int => println (i*i)
case _ => // Int가 아닌 경우 처리
}
이것 역시 Scala가 더 낫다.
Annotation
아래의 Java 어노테이션을 Scala에서 쓴다고 해보자.
package test;
import java.lang.annotation.*;
@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConsAnnotation {
}
이 어노테이션을 아래 class의 생성자에 붙이려면 아래처럼 하면 될 것 같다.
package test
@ConsAnnotation
class TargetClass1 (num:Int){
}
컴파일해보면 잘 된다. 하지만 아래코드를 실행해보면
package test
object Run1 {
def main(args:Array[String]) {
val cls = classOf[TargetClass1] ;
println(cls + " ==> " + cls.getAnnotation(classOf[ConsAnnotation])) ;
cls.getConstructors().foreach{ cons =>
println(cons + " ==> " + cons.getAnnotation(classOf[ConsAnnotation])) ;
}
}
}
뭔가 문제가 있음을 알 수 있다.
class test.TargetClass1 ==> @test.ConsAnnotation() public test.TargetClass1(int) ==> null
이렇게 하면 생성자가 아니라 클래스에 어노테이션이 붙는다. 생성자에 붙이려면 아래처럼 클래스명과 매개변수 리스트 사이에 어노테이션을 넣어야 한다. 그리고 어노테이션에 매개변수를 넣지 않더라도 ()
를 꼭 붙여야 한다.(안 붙이면 컴파일 오류가 난다.)
package test
class TargetClass2 @ConsAnnotation()(num:Int ){
}
class test.TargetClass2 ==> null public test.TargetClass2(int) ==> @test.ConsAnnotation()
이 어노테이션은 생성자에만 붙도록 되어있음에도 클래스에 붙일 수 있다는 것은 뭔가 이상하다. 내가 확인해본 바로는 scalac는 어노테이션의 Target
설정을 확인하지 않는다고 한다.