2012년 8월 29일 수요일

내부클래스와 익명클래스


익명 클래스의 용도는 문법적으로 봤을 때 어렵지는 않습니다만.. (쉽게 말해서 클래스 안에 클래스를 다시 선언하는 방식) 문제는 그 사용법을 정확한 포인트에 넣어주는 것이 상당히 어려운 문제입니다.

 익명클래스를 선언하는 경우에 얻을 수 있는 최대의 장점은 객체가 필요한 데이터를 매번 전달받는 방식이 아니라.. 기생하고 있는 클래스에서 바깥쪽의 객체가 가지는 데이터를 그대로 사용할 수 있다는 점이 최대의 장점입니다.


public class OuterA {

        private String name;
       
        private  class InnerA{
               public void display(){
                       System.out.println(name);
               }
        }
       
       
        public InnerA getInstance(){
              
               return new InnerA();
              
        }
       
       
        public static void main(String[] args) {
              
               OuterA outer = new OuterA();
              
               System.out.println(outer.getInstance());
               System.out.println(outer.getInstance());
               System.out.println(outer.getInstance());
              
              
        }
}
예를 들어 위와 같은 경우에는 외부에서 직접적으로 InnerA클래스의 객체를 생성할 수 없도록 설계할 수 있습니다. 게다가 더 강력한 점은 모든 InnerA클래스의 객체가  OuterA객체의 name값을 자동적으로 참조하도록 설계할 수 있다는 사실 입니다.

이런 방식을 이용하면 객체들이 같이 공유해야 하는 데이터를 처리하는 하는 데에 좀 더 편리해 질 수 있습니다.

inner클래스를 사용하게 되면 누릴 수 있는 최대의 장점은 역시나 자바 언어의 가장 문제점인 메소드의 파라미터와 리턴타입의 종속적인 문제를 해결하는데에도 도움이 될 수 있습니다.

예를 들어 다음과 같은 인터페이스를 생각해 봅니다.

public interface Connector {
       
        public void execute()throws RuntimeException;

}

인터페이스의 가장 큰 문제점은 추상 메소드 자체가 상당히 고정적이라는 겁니다. 즉 어떤 클래스에서 구현하게 되면 파라미터나 리턴타입을 처리할 수 없게 되는 문제를 가집니다. 익명 클래스를 이용하게 되면 이러한 단점을 커버할 수 있습니다.

public class Job {

        public void doJob(String webURL)throws Exception{
              
               final URL url = new URL(webURL);
              
               final InputStream in = url.openStream();
              
               final OutputStream out = new FileOutputStream("");
              
               new Connector(){

                       @Override
                       public void execute() throws RuntimeException {
                             
                              try {
                                      in.read();
                                      out.write(11);                              
                              } catch (IOException e) {
                                      // TODO Auto-generated catch block
                                      e.printStackTrace();
                              }
                             
                       }
                      
               }.execute();
              
               out.close();
               in.close();
              
              
              
        }
}
위의 코드를 보면 익명 클래스를 이용해서 파라미터의 전달 없이 필요한 모든 자원을 메소드 내에서 조달하는 것을 볼 수 있습니다. 이 작업을 별도의 객체로 만들면 상당히 복잡하지만 익명 클래스에서는 final 키워드를 조합해서 사용하는 방식으로 동작하면 되기 때문에 별도의 제약이 없이 사용할 수 있습니다.


제가 간단하게 예를 들어 설명했지만, 익명 클래스나 내부 클래스의 경우에는 실제 코드를 작성할 때 쉽게 나오는 개념은 아닙니다. 현실적으로는 안드로이드의 예제들을 보면 제한된 상속내에서 익명 클래스를 이용하는 것을 많이 볼 수 있는데, 이러한 것은 기존의 설계가 인터페이스 기반으로 튼튼하게 설계된 경우에 빛을 볼 수 있습니다.

..역시 설명이 너무 어렵네요..^^;;;;

2012년 8월 19일 일요일

상속과 조합에 대한 단상



public interface DeviceRole {

 public void execute();

}





---------------------------------------------------------------------------
4가지의 기능들

public class CreateRole implements DeviceRole {

 @Override
 public void execute() {

  System.out.println("You Can Create.........");
 }

}


public class ReadRole implements DeviceRole {

 @Override
 public void execute() {

  System.out.println("You Can Read.....");
 }

}



public class UpdateRole implements DeviceRole {

 @Override
 public void execute() {

  System.out.println("You can Update...");
 }

}




public class DeleteRole implements DeviceRole {

 @Override
 public void execute() {

  System.out.println("You Can Delete");
 }

}
--------------------------------------------------------------------

4가지의 기능들을 조합해서 사용할 수 있는 사용자 객체

상속으로 한다면 기능의 경우에 수에 맞게 객체를 생성해야만 하지만, 인터페이스와 조합의 경우에는
그럴 필요가 없다.


import java.util.ArrayList;
import java.util.List;


public class User {

 private List<DeviceRole> roleList;


 public User(){

  roleList = new ArrayList<DeviceRole>();
 }


 public List<DeviceRole> getRoleList() {
  return roleList;
 }


 public void setRoleList(List<DeviceRole> roleList) {
  this.roleList = roleList;
 }




}