YourInteger 라는 스칼라 클래스를 생성하고, + 연산을 할 수 있는 메소드를 추가한다.
class YourInteger(i : Int) {
val number = i
def method(given : Int) = {
println("Hi " + given);
}
def plus(given : Int):YourInteger = {
new YourInteger(given + number)
}
override def toString() = {
"" + number
}
}
YourInteger 객체를 생성하고 + 연산을 해본다.
val a = new YourInteger(5);
println(a)
결과는 다음과 같다.
5
YourInteger 클래스의 method를 호출하면 당연히 잘 되지만, 반대의 케이스는 에러가 발생한다.
val b = a.method(1) // b는 컴파일 성공
val c = 1.method(3) // c는 컴파일 에러
컴파일러는 overloaded method value + with alternatives를 출력하는 에러가 발생한다.
암묵적 타입 변환인 implicit def를 선언하면, int에 대해 YourInteger의 메소드를 실행할 수 있다. ruby처럼 static duck typing 기법에 대해서 조금 알았다.
val a = new YourInteger(5);implicit def intToYourInteger(x: Int) = new YourInteger(x);
println(a)
val b = a.method(1)
val c = 1.method(3)
val d = 1.plus(2)
실행 코드에 implict 구문이 있으면 지저분해서 조금 변경할 수 있다.
YourInteger 클래스 파일에 YourInteger 객체를 선언한 후, 묵시적 타입 변환을 추가한다.
class YourInteger(i : Int) {
val number = i
def method(given : Int) = {
println("Hi " + given);
}
def plus(given : Int):YourInteger = {
new YourInteger(given + number)
}
override def toString() = {
"" + number
}
}
object YourInteger {
implicit def intToYourInteger(x: Int) = new YourInteger(x);
}
실행 코드에서 import를 하고..
import YourInteger._
실행할 메소드에서 다음을 사용하면 실행된다.
val a = new YourInteger(5);
println(a)
val b = a.method(1)
val c = 1.method(3) println(c)
val d = 1.plus(2)
javap로 확인하면 다음과 같다.
$ javap YourInteger.class
Compiled from "YourInteger.scala"
public class YourInteger {
public static YourInteger intToYourInteger(int);
public int number();
public void method(int);
public YourInteger plus(int);
public java.lang.String toString();
public YourInteger(int);
}
$ javap YourInteger$.class
Compiled from "YourInteger.scala"
public final class YourInteger$ {
public static final YourInteger$ MODULE$;
public static {};
public YourInteger intToYourInteger(int);
}
좀 더 내부를 파고 싶다면, class파일을 디컴파일하는 jad(http://varaneckas.com/jad/)를 이용한다.
YourInteger.scala를 컴파일한 scala파일의 java 구현체(YourInteger, YourInteger$)는 다음과 같다. Predef 외에는 특별한 내용이 없다.
import scala.Predef$;
import scala.collection.mutable.StringBuilder;
import scala.runtime.BoxesRunTime;
public class YourInteger
{
public static YourInteger intToYourInteger(int i)
{
return YourInteger$.MODULE$.intToYourInteger(i);
}
public int number()
{
return number;
}
public void method(int given)
{
Predef$.MODULE$.println((new StringBuilder()).append("Hi ").append(BoxesRunTime.boxToInteger(given)).toString());
}
public YourInteger plus(int given)
{
return new YourInteger(given + number());
}
public String toString()
{
return String.valueOf(BoxesRunTime.boxToInteger(number()));
}
public YourInteger(int i)
{
number = i;
}
private final int number;
}
public final class YourInteger$
{
public YourInteger intToYourInteger(int x)
{
return new YourInteger(x);
}
private YourInteger$()
{
}
public static final YourInteger$ MODULE$ = this;
static
{
new YourInteger$();
}
}
실행 코드의 디컴파일 결과이다. 묵시적 타입 변환은 BoxedUnit이라는 클래스를 활용했다.
YourInteger a = new YourInteger(5);
Predef$.MODULE$.println(a);
a.method(1);
BoxedUnit b = BoxedUnit.UNIT;
YourInteger$.MODULE$.intToYourInteger(1).method(3);
BoxedUnit c = BoxedUnit.UNIT;
Predef$.MODULE$.println(c);
YourInteger d = YourInteger$.MODULE$.intToYourInteger(1).plus(2);
아래 scala 코드에 대한 자바코드를 살펴본다.
val c = 1.method(3) println(c)
1.method는 아래와 같은 자바 코드로 변환한다.
YourInteger$.MODULE$.intToYourInteger(1).method(3);
BoxedUnit c = BoxedUnit.UNIT;
Predef$.MODULE$.println(c);
'scala' 카테고리의 다른 글
[scala 2.11.8] 간단한 변수 스코프 테스트시 유의사항 (0) | 2016.04.04 |
---|---|
[scala] jad로 디컴파일(decompile)하기, javap, scalac 사용하기 (0) | 2016.03.26 |
[scala] 싱글톤 객체, 독립 객체, 동반 클래스 (0) | 2016.03.24 |
[scala] =과 함수 선언 (0) | 2016.03.23 |
[Scala] List의 sort는 deprecated, sortWith, sortBy, sorted 활용 예시 (0) | 2016.03.22 |