레이블이 객체중심Java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 객체중심Java인 게시물을 표시합니다. 모든 게시물 표시

2011년 2월 19일 토요일

안드로이드 지도 프로그래밍 자료 올립니다.

안드로이드를 이용하는 지도 프로그램 만드는 부분

추가 원고로 제공용으로 만든 것입니다.

주요 내용은 다음과 같습니다.

- Activity에 지도 보이는 설정 및 예제 만드는 요령
- Location Manager를 이용해서 자신의 위치를 파악하는 방법
- 지도 상에서 원하는 좌표로 이동하기

- Overlay를 이용해서 지도위에 마커 표시하기
- 일반 Overlay와 ItemizedOverlay의 차이 및 사용법
- 지도 상의 주소 데이터 얻기, 주소 데이터 변환하기

안드로이드지도프로그래밍자료얻기


- 파일 용량이 4M정도인데 Google 문서로 열면 조금 로딩 속도가 걸리네요..

- 다운로드 받으실 분들은 Freelec 출판사의 강의실에서 다운로드 받으실 수 있습니다.

2011년 1월 18일 화요일

왜 수많은 디자인패턴은 인터페이스로 구현하게 되는가?

아마도 Java를 공부하는데 있어서 가장 험난한 고비는 역시 interface가 아닌가 싶다.
하긴 나도 인터페이스를 10년이 넘은 지금도 '이게 최선입니까? , 확실해요? '라는 질문을 던지고 있으니 초급자들에게는 가장 넘기 어려운 산일 것이다.

상속이라는 것은 초급자들이 좀 쉽게 적응을 할 수 있다는 것은 너무나 명확한 사실인듯하다.

하지만 인터페이스의 경우는 어떤가? 솔직히 전혀 아니올시다..

그럼 여기서 우리가 한번 생각해 봐야하는 것은 '왜 그 수많은 객체지향 디자인 패턴은 상속보다는 인터페이스를 사용하는가?'이다.

우선 인터페이스의 몇 가지 특징을 생각해 보자.

인터페이스는 컴파일러가 인식하는 하나의 코드에 대한 스펙을 의미한다.

즉 어떤 객체이건 간에 특정 메소드를 오버라이드하고 있는 객체라면 컴파일러는 지나칠 수 있다는 뜻이다.
사실 이 특징은 다형성이라는 것이 가지는 장점이라고 생각해도 되고, 상속 역시 다형성의 일부이기 때문에 굳이 인터페이스에 국한된 설명이라고 할 수는 없다.


인터페이스는 온갖 다른 클래스를 하나의 타입과 동일한 메소드의 오버라이드라는 놀라운 효과를 가져온다.
아무리 다른 로직들(메소드들)과 데이터를 가진 객체들이라고 할 지라도 동일한 인터페이스를 구현하므로 인해서 모든 객체들을 하나의 타입으로 아우룰수 있는 최고의 방법이다.
흔히들 Java에서 인터페이스를 'Java의 꽃'이라고 부르는 것도 이러한 이유이다.

켄트 백의 말처럼 인터페이스의 가장 무서운 점은 '인터페이스를 바라보고 코드를 작성할 때에는 실제 인터페이스 너머에는 어떤 객체가 존재하는지 신경쓰지 않아도 된다'는 점이다.

-------------------------------------------------------------------------------
인터페이스가 왜 유연한지 생각해보자면 가장 쉽게 점심메뉴를 생각해 보시라..

'오늘은 카레를 먹을꺼야' VS '오늘은 따끈한 국물요리를 먹을꺼야'

'카레'를 먹는 방식은 클래스와 객체 방식이다. 왜냐하면 이 말을 통해서 우리가 바로 어떤
실체를 떠올릴 수 있기 때문이다.

반면에 '따끈한 국물요리'는 인터페이스 방식이다. 이 말을 통해서는 실체를 떠올릴 수는 없다. 왜냐하면 너무나 많은 국물 요리 후보 객체가 생겨버리기 때문이다.

객체지향이 현실세계를 모델로 한다고 하자. 우리가 점심메뉴는 어떤 방식을 선택하는가?
클래스인가? 아님 인터페이스 인가?

2011년 1월 12일 수요일

상속은 위험하다(1)

자바나 C#등 모든 OOP에서 모든 개발자들이 가장 쉽게 접근하여 사용할 수 있는 개념은 바로 상속이다.

상속은 쉬울뿐 아니라 강력한 기능을 가지고 있다는 데에는 의견이 없다.

하지만 이러한 구현 클래스에 의한 상속은?

-----------------------------------------------------------------------------
public class PClass {
 
 
 private PClass target;
 
 public void setTarget(PClass target){
  this.target = target;
 }
 
 public void doA(){
  target.doA();
 }
}

-----------------------------------------------------------------------------

public class SClass extends PClass {
 
 public void init(){
  super.setTarget(this);
 }
 public void doA(){
  System.out.println("sub....");
  super.doA();
 }
 
 
 public static void main(String[] args) {
  
  SClass s = new SClass();
  s.init();
  s.doA();
  
 }
}
-----------------------------------------------------------------------------

위의 소스를 보자.
물론 예제를 만들기 위한 편협한 소스이지만 분명한 건 컴파일 시에는 위의 코드는 문제가 없다.

만일 당신이 이 소스의 문제가 클래스라고 말한다면 어쩔 수 없다. 반쯤은 동의할 의향이 있기 때문에..
하지만 좀 더 생각해 보면 상속이라는 구조가 성립되지 않는다면 위의 소스는 컴파일 자체가 불가능하다는 사실을 인정하기 바란다.

실행결과는 명확하다. StackOverflow가 발생한다.

이러한 상속을 소위 '깨지기 쉬운 상속'이라고 얘기할 수 있다.


구현 클래스를 이용해서 하는 코딩이라면 극단적으로 위와 같은 방식의 코딩도 가능하다는 얘기다.
따라서 상속을 이용하는 경우에는 하위에서 어떤 방식으로 오버라이딩이 되었는지 모르기 때문에 발생하는 문제가 더 크다는 얘기다.

2011년 1월 10일 월요일

java.lang.Object에 대한 단상

Java에서 상속과 관련해서 반드시 언급해야 하는 클래스가 java.lang.Object클래스일 것이다.

초급자의 입장에서는 가장 많이 의문을 가지는 클래스이기도 할 것이다.
어째서 java.lang.Object라는 클래스가 존재하는가?

어째서 java.lang.Object클래스에 몇 가지 메소드들이 정의되어 있는가?

    public native int hashCode();
    public final native Class<?> getClass();
    public boolean equals(Object obj) {
      return (this == obj);
    }

native라는 키워드는 언제 사용되는 것인가?

native 키워드는 JNI를 이용한 통신에 사용되는 키워드라고 생각하면 된다.
JNI를 이용하는 프로그래밍의 순서는 다음과 같다
  • Write Java code
  • Compile Java code
  • Create C header (.h file)
  • Create C stubs file
  • Write C code
  • Create shared code library (or DLL)
  • Run application

native 메소드가 java.lang.Object에 정의되어 있다는 것은 간단하게 말해서
소위 말하는 운영체제와 연결되는 코드를 가지고 있다는 것을 의미한다.

상속에서 가장 상위의 클래스는 java.lang.Object이다. 그렇다면 어떤 객체를 만들때 마다
java.lang.Object 클래스의 객체 역시 만들어 진다는 것을 의미한다.

상속이 가장 많이 사용되는 것은 당연히 원래의 코드를 그대로 물려주는 기능이다.
그렇다면 모든 객체가 운영체제와 통신하는 native 메소드를 물려주었다는 것은 Java에서 만들어진 모든 객체는 직접 운영체제와 통신할 필요가 있다는 것을 의미한다.


운영체제와 직접 통신해야 하는 부분이 무엇인가?
이 질문에 해답은 운영체제의 스레드에 있다.

즉 JVM을 벗어나 운영체제와 통신하는 코드가 있다는 것은 스레드와 같은 이슈의 해결을 위해서는 결과적으로 직접 호출하는 방식을 사용한다는 것을 의미한다.

결국에 JVM에서 객체가 생성되는 것은 순수하게 Java Virtual Machine만을 사용하는 것이 아니라 운영체제의 메모리의 구조도 같이 사용하게 된다는 것을 의미한다.

2011년 1월 4일 화요일

접근제한자가 객체지향의 중요한 특징이라고?

흔히들 객체지향 언어의 특징중에 하나로 '정보 은닉'이라는 것을 든다.

접근제한이라는 설명을 하면서 이런 특징을 설명하는데..
사실 이것은 객체지향 패러다임과 관련이 있다고 할 수 있는지에 대해서는 아직도 의문이 든다.

왜 내가 이런 생각을 하는지 한번 얘기를 풀어보도록 하자.

우선 객체지향 패러다임에서 객체(object)라는 것은 언어로 말하자면 변수를 별도의 공간에 각 각 저장하는 방식을 의미한다. 즉 Java의 경우라면 클래스의 복사본의 구조를 그대로를 메모리 상에 별도의 영역에 할당하는 방식이다.

이렇게 되면 각 메모리의 공간을 접근하기 위해서 포인터(pointer)를 활용하게 될 것이고,
그것을 Java에서는 레퍼런스라는 이름으로 부르고 있다.

접근제한이라는 것은 간단히 말하자면 이 공간에 접근하는 것을 특정한 키워드를 이용해서 제어하는 것을 의미한다.

즉 접근 제한이라는 것은 메모리 공간을 마음대로 접근하지 못하게 하는 행위를 의미하는 것이지, 객체지향에서만 사용되는 특별한 개념은 아니라는 것이다.


접근 제한이라는 말 보다는 오히려 데이터나 로직에 접근할 수 있는 하나의 울타리나 상황(Context)라는 개념이 더욱 적합한 개념이 아닐까?

-----------------------------------------------------------------
사실 접근 제한을 보면 상당히 말도 안되는 구성을 가지고 있다.

우선 가장 접근제한 레벨이 높은 private을 한번보자.

private은 외부 클래스에서는 접근이 불가능하다는 판단이다. 재밌는 것은 이 범위라는 것이 단순히 클래스의 '{ }'에 대해서만 한정적이라는 사실이다.


public class Save {

private int total;
public void addMoney(int amount){
total = total + amount;
}
public void withdraw(int amount){
total = total - amount;
}
public void displaySave(){
System.out.println("CURRENT :" + total);
}
}

위의 코드를 보자. 
total이라는 데이터가 private으로 정의되어 있다. 따라서 외부의 클래스에서는 이 데이터에 access를 할 수 없게 되어 있다. 

하지만 이 접근 제한은 만일 객체를 사용하는 main 메소드를 안쪽에 만들어 버리면 참으로 무용지물이 된다. 


public class Save {

private int total;

---- 중략
public void displaySave(){
System.out.println("CURRENT :" + total);
}

public static void main(String[] args) {
Save s1 = new Save();
s1.total = 1000;
s1.displaySave();
}
}


위의 코드는 실제로 에러가 발생하지도 않고, 실행되 제대로 된다.
이 코드를 보면 객체지향에서의 '정보의 은닉'이라는 것은 절대 환상이다.
만일 정말로 객체의 정보가 은닉되어서 감추어 진다면 main메소드가 실행되는 환경에서조차도 s1이 가진 정보는 보호되어야 하지 않을까?

-----------------------------------------------------------------------
그렇다면 우리는 도대체 private을 뭐라고 이해해야만 하는 것일까?

일단은 우리가 쉽게 Java책들에서 찾아볼 수 있는 개념을 한번 정리해 보자.

* 접근제한을 하면 외부 클래스에서 접근할 수 없다(private)

* 하지만 private이라고 해도 동일한 클래스 내에서는 접근이 가능하다. static이건 아니건 상관은 없다.

이 두가지 사실만으로 판단해 보면 결국 접근제한을 한다는 것은 마치 코드의 영역을 표시해 주는 '{ }'와 유사하지 않을까?

예를 들어 조금은 과장된 방식의 코드를 작성해 보자.


public class ForEx {

{
int j = 10; 
for(int i = 0; i < 10; i++){
System.out.println(i + j);
}
}
}



이 코드는 전혀 문제가 없는 코드이다. '{ }'를 이용해서 변수의 범위에 대한 제한을 걸어 둔 것 뿐이다.


public class ForEx {

{
int j = 10; 
for(int i = 0; i < 10; i++){
System.out.println(i + j);
}
}
//이러면 에러 
j++;
}
재밌는 것은 접근제한 보다도 오히려 위와 같은 '{ }'가 변수나 로직에 대한 접근을 더욱 엄격하게 할 수 있다는 것이다. 


이제 슬슬 결말로 가보자. 

우리가 배우는 접근제한자 라는 것은 우리가 생각했던 것만큼 객체지향적이지도 않을 뿐더러 프로그래밍에서 영역을 구분하는 '{ }'보다도 못하다는 것이다. 

그럼 접근제한자를 왜 생각해 냈을까?  
클래스의 내부에서만 사용되는 변수? 

동일한 정보(클래스는 일종의 메타데이터이므로)를 가지는 것들만의 일종의 필터(filter)가 아닐까? 

필터(filter)라는 가정을 해 보자. 

모든 객체는 자신이 속한 클래스의 정보를 알아 낼 수가 있다. 흔히 reflection기술을 이용하면 이 사실을 좀 더 알수 있을 것이다. 

만일 A라는 객체와 B라는 객체가 동일한 클래스에서 나온 객체라면 이 두 객체는 서로가 동족(? 동일한 클래스에서 생성되었음)이라는 것을 알수 있을 것이다. 

그렇다면 이 동족들 사이에서만 사용될 수 있는 일종의 변수의 이름을 생각해 보면 어떨까? 
private이 붙은 변수는 즉 이런 동일한 족속들이 사용하는 일종의 정해진 변수의 이름이라고만 생각해 보면 어떨까? 

default 접근제한자의 경우라면 동일한 패키지의 이름으로  정보를 가진 객체만 사용하는 '은어'와 같은 존재라고 보면 어떨까? 


내가 생각하는 접근제한자라는 것은 이런 개념이다.