안드로이드 NFC 예제를 보면서 괜찮은 기법이 있어서 소개할까합니다. (저만 몰랐던 걸 수도 있구요. :D )
제가 본 소스의 일부를 쓰자면
맵에 요소를 넣으면서 URI_PREFIX에 인스턴스를 할당하는 구문입니다.
처음 봤을 때는 저게 원래 자바에서 지원하는 문법인가 싶어서 객체 안에 있는 메서드
위처럼 세미콜론 없이 닷만 찍어서 계속 해보려했는데 당연히도 에러가 나더군요.
위 문장을 보고 저게 뭐? 라고 생각하셨다면 아래에 쓰는 체이닝 기법을 적용하지 않고 작성한 소스를 보고 비교해보세요.
개인적인 차이일지도 모르겠지만 저는 체이닝 기법을 적용한 소스가 더 깔끔하고 직관적으로 느껴지네요. 서론은 여기까지 하고 실제로 어떻게 체이닝 기법을 적용할 수 있는지 예제를 만들면서 알아봅시다.
만들 클래스는 간단한 학생 정보 클래스입니다. 체이닝 기법을 적용한다고 해서 그리 효율적인 클래스가 되진 않겠지만 간단한 예를 위해서 이 클래스를 씁니다.
위 클래스에서 생성자를 두지 않는다고 가정하면 학생 인스턴스에 정보를 넣기위해서는 아래와 같이 코드를 작성하게 되겠죠
체이닝 기법을 적용하기 위해서 뮤테이터(세터) 메서드의 반환형을 void에서 오브젝트를 반환하도록 Student 타입으로 바꿔 줍니다.
그리고 메서드 구현부의 끝에 return this;를 써서 객체를 반환하도록 하구요.
DSL에서는 setName과 같은 메서드 이름도 더 직관적으로 바꾸지만 익숙함을 위해서 그대로 쓰도록 하겠습니다. 위의 Student 클래스를 체이닝 기법을 적용하기 위한 소스로 바꿔보면 아래와 같습니다. 빨간색 글씨가 수정된 부분입니다
클래스를 바꿨으니 인스턴스를 할당할 때도 바로 적용해 봅시다.
네. 이상입니다.
원리는 간단합니다. 계속해서 객체를 반환하니 메서드를 다시 호출해서 쓸 수 있고. 역시 student 변수는 Student 클래스 타입이니 반환한 객체 그대로 받을 수 있게 됩니다.
제가 본 소스의 일부를 쓰자면
BiMap<Byte, String> URI_PREFIX = BiMap.<Byte, String>builder()
.put((byte) 0x00, "")
.put((byte) 0x01, "http://www.")
.put((byte) 0x02, "https://www.")
.put((byte) 0x03, "http://")
.put((byte) 0x04, "https://")
.put((byte) 0x05, "tel:")
.build();
맵에 요소를 넣으면서 URI_PREFIX에 인스턴스를 할당하는 구문입니다.
처음 봤을 때는 저게 원래 자바에서 지원하는 문법인가 싶어서 객체 안에 있는 메서드
위처럼 세미콜론 없이 닷만 찍어서 계속 해보려했는데 당연히도 에러가 나더군요.
위 문장을 보고 저게 뭐? 라고 생각하셨다면 아래에 쓰는 체이닝 기법을 적용하지 않고 작성한 소스를 보고 비교해보세요.
BiMap<Byte, String> URI_PREFIX =
BiMap.<Byte, String>builder().build();
URI_PREFIX.put((byte) 0x00, "");
URI_PREFIX.put((byte) 0x01, "http://www.");
URI_PREFIX.put((byte) 0x02, "https://www.");
URI_PREFIX.put((byte) 0x03, "http://");
URI_PREFIX.put((byte) 0x04, "https://");
URI_PREFIX.put((byte) 0x05, "tel:");
URI_PREFIX.put((byte) 0x01, "http://www.");
URI_PREFIX.put((byte) 0x02, "https://www.");
URI_PREFIX.put((byte) 0x03, "http://");
URI_PREFIX.put((byte) 0x04, "https://");
URI_PREFIX.put((byte) 0x05, "tel:");
개인적인 차이일지도 모르겠지만 저는 체이닝 기법을 적용한 소스가 더 깔끔하고 직관적으로 느껴지네요. 서론은 여기까지 하고 실제로 어떻게 체이닝 기법을 적용할 수 있는지 예제를 만들면서 알아봅시다.
만들 클래스는 간단한 학생 정보 클래스입니다. 체이닝 기법을 적용한다고 해서 그리 효율적인 클래스가 되진 않겠지만 간단한 예를 위해서 이 클래스를 씁니다.
/** 학생정보 클래스 */
class Student{
class Student{
private String name; // 학생이름
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과
public void setName(String name){
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과
public void setName(String name){
this.name = name;
}
public void setNumber(String number){
public void setNumber(String number){
this.number = number;
}
public void setBirthyear(int birthyear){
public void setBirthyear(int birthyear){
this.age = age;
}
public void setDept(String dept){
public void setDept(String dept){
this.dept = dept;
}
/* getter 생략 */
/* getter 생략 */
}
위 클래스에서 생성자를 두지 않는다고 가정하면 학생 인스턴스에 정보를 넣기위해서는 아래와 같이 코드를 작성하게 되겠죠
Student student = new Student();
student.setName("세종대왕");
student.setNumber("7284910");
student.setBirthyear(1397);
student.setDept("국어국문학과");
체이닝 기법을 적용하기 위해서 뮤테이터(세터) 메서드의 반환형을 void에서 오브젝트를 반환하도록 Student 타입으로 바꿔 줍니다.
그리고 메서드 구현부의 끝에 return this;를 써서 객체를 반환하도록 하구요.
DSL에서는 setName과 같은 메서드 이름도 더 직관적으로 바꾸지만 익숙함을 위해서 그대로 쓰도록 하겠습니다. 위의 Student 클래스를 체이닝 기법을 적용하기 위한 소스로 바꿔보면 아래와 같습니다. 빨간색 글씨가 수정된 부분입니다
/** 학생정보 클래스 */
class Student{
class Student{
private String name; // 학생이름
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과
public Student setName(String name){
private String number; // 학번
private int birthyear; // 생년
private String dept; // 학과
public Student setName(String name){
this.name = name;
return this;
return this;
}
public Student setNumber(String number){
public Student setNumber(String number){
this.number = number;
return this;
return this;
}
public Student setBirthyear(int birthyear){
public Student setBirthyear(int birthyear){
this.age = age;
return this;
return this;
}
public Student setDept(String dept){
public Student setDept(String dept){
this.dept = dept;
return this;
return this;
}
/* getter 생략 */
/* getter 생략 */
}
클래스를 바꿨으니 인스턴스를 할당할 때도 바로 적용해 봅시다.
Student student = new Student()
.setName("세종대왕")
.setNumber("7284910")
.setBirthyear(1397)
.setDept("국어국문학과");
네. 이상입니다.
원리는 간단합니다. 계속해서 객체를 반환하니 메서드를 다시 호출해서 쓸 수 있고. 역시 student 변수는 Student 클래스 타입이니 반환한 객체 그대로 받을 수 있게 됩니다.
'밤을 지새다 > Java' 카테고리의 다른 글
Java StAX: XMLInputFactory (0) | 2012.04.30 |
---|---|
Java StAX (0) | 2012.04.30 |
Exceptions (0) | 2011.09.05 |
자바. 얼마나 알고 사용하고 계신가요? (0) | 2011.08.25 |
객체를 바이트 배열로, 바이트 배열을 객체로 (0) | 2011.08.22 |