2012-07-30 3 views
3

Java에서 함수 객체를 구현하려고합니다. Unit 클래스의 대부분의 초기화에서 사용해야하는 기본 추가 함수가있는 Unit 클래스가 있습니다. 그러나 일부 문제의 경우 다른 추가 기능이 필요합니다.자바에서 객체 함수 사용

public class Unit() { 
    public Unit(unitType) { 
     if (unitType == "specialType") { 
     additionFunc = defaultFunc } else { 
     additionFunc = specialFunc } 
     } 
    } 
    public int swim() { 
     return additionFunc() 
    } 
    // definiion of regularFunc 
    // definition of specialFunc 

} 

그런 다음, 주요 파일 :

Unit fish = new Unit(regularTyoe); 
Unit fatFish = new Unit(specialType); 
fish.swim(); //regular function is called 
fatFish.swim(); //special function is called 

가 ... 누군가가이 작업을 수행 할 수있는 방법을 알고 않는 것 코드는 다음과 같이 보일 것인가?

답변

1

내가 그것을 의해 할 수 있다고 생각이 작업을 수행하는

+0

이 모든 답은 나를 노버 그 어느 때보 다 더 :) 이것이 내가 필요로하는 것에 가장 가까운 것 같습니다 –

2

단위를 확장하고 swim()을 재정의하는 새로운 FatFish 클래스를 만듭니다.

Unit fish = new Unit(); 
Unit fatFish = new FatFish(); 
fish.swim(); //regular function is called 
fatFish.swim(); //special function is called 
4

당신은 inheritancemethod overriding를 찾아 볼 필요가있다. 적절한 객체 지향 프로그래밍을 읽는 것이 도움이 될 것입니다.

이 작업을 수행하는 적절한 방법은 다음과 같습니다 if 문 간단한 사용

class Fish { 
    public void swim() { 
    // normal swim 
    } 
} 

class FatFish extends Fish { 
    @Override 
    public void swim() { 
    // special swim 
    } 
} 

Fish fish = new Fish() 
Fish fatFish = new FatFish() 
fish.swim() // normal swim 
fatFish.swim() // slow swim 
+0

이 유일한 방법은 당신이 할 수있는 개체를 인스턴스화하기 위해

public interface SwimStrategy { void execute(); } public class FatFishSwimStrategy implements SwimStrategy { @Override public void execute() { // fat fish swim impl } } public class FishSwimStrategy implements SwimStrategy { @Override public void execute() { // normal fish swim impl } } public class Fish { private final SwimStrategy swimStrategy; public Fish(SwimStrategy swimStrategy) { this.swimStrategy = swimStrategy; } public void swim() { swimStrategy.execute(); } } 

: 따라서 당신은 같은 일을 할 수 있을까? 자바에서 함수 객체가 없습니까? : (( –

+0

@ n00bprogrammer .... 함수는 Java에서 first-class 객체가 아닙니다. 당신이하려고하는 것을 해킹 할 수있는 방법이 있지만, 모든 레벨에서 잘못된 접근법이 있습니다.) –

1

:

private String unitType; 

public Unit(unitType) { 
    this.unitType = unitType;  
} 

public int swim() { 
    if (unitType.equals("specialType") { 
     return specialFunc(); 
    } 
    else { 
     return regularFunc(); 
    } 
} 

또는 다형성 및 팩토리 메소드를 사용 :

public abstract class Unit() { 

    protected Unit() { 
    } 

    protected abstract int addition(); 

    public int swim() { 
     return addition(); 
    } 

    public static Unit forType(String unitType) { 
     if (unitType.equals("specialType") { 
      return new SpecialUnit(); 
     } 
     else { 
      return new RegularUnit(); 
     } 
    } 

    private static class SpecialUnit extends Unit { 
     @Override 
     protected addition() { 
      // special addition 
     } 
    } 


    private static class RegularUnit extends Unit { 
     @Override 
     protected addition() { 
      // regular addition 
     } 
    } 
} 

또는를 사용하여 Adderaddition() 메서드를 정의하는 기능 인터페이스와 2 개의 co 이 인터페이스의 ncrete 구현 :

private Adder adder; 

public Unit(unitType) { 
    if (unitType.equals("specialType") { 
     this.adder = new SpecialAdder(); 
    } 
    else { 
     this.adder = new RegularAdder(); 
    } 
} 

public int swim() { 
    return adder.addition(); 
} 

이 마지막 하나는 당신이 당신의 질문에 질문 원하든에 가장 가까운 것입니다. 함수 객체는 그 자체로 존재하지 않지만 인터페이스로 대체 될 수 있습니다.

1

Java에서이 다형성 동작을 수행하는 데는 두 가지 방법이 있습니다. 첫 번째는 상속과 계층 적 클래스 집합을 사용하는 것입니다. 예를 들어 "swim"이라는 추상 메서드를 정의하는 추상 기본 클래스를 가질 수 있습니다. 그런 다음 각 구체적인 물고기 클래스는이 기본 클래스를 확장하고 수영 메서드를 구현합니다. 나중에 물고기 개체 집합이있을 때 기본 클래스로 업 캐스트하고 각각에 대해 swim 메서드를 호출 할 수 있습니다.

두 번째 방법은 인터페이스를 사용하는 것입니다. 공용 메서드 수영을 선언하는 인터페이스 (예 : ISwim)를 정의합니다. 각 어류 클래스 (클래스 계층 구조 또는 아니요의 일부)는 ISwim 인터페이스를 구현하므로 수영 메서드를 정의합니다. 그런 다음 서로 다른 유형의 물고기 클래스 개체 집합이있는 경우 각각을 ISwim 인터페이스로 캐스팅하고 각 개체에서 swim 메서드를 호출 할 수 있습니다.

자바에는 기능 포인터가 없으므로 고려중인 접근 방식은 해당 언어에 적합하지 않습니다. 함수 포인터가있는 언어에서도 위의 두 가지 방법이 내 의견으로는 가장 적절할 것입니다.

public class Unit { 
    public enum UnitType { 
     REGULAR { 
      public Unit makeUnit() { 
       return new RegularUnit(); 
      } 
     }, 
     SPECIAL { 
      public Unit makeUnit() { 
       return new SpecialUnit(); 
      } 
     }; 
     abstract public Unit makeUnit(); 
    } 
    protected Unit() {} 
    public abstract int swim(); 
    private static class RegularUnit extends Unit { 
     RegularUnit() {} 
     public int swim() { 
      return 0; 
     } 
    } 
    private static class SpecialUnit extends Unit { 
     SpecialUnit() {} 
     public int swim() { 
      return 1; 
     } 
    } 
} 

Unit fish = UnitType.REGULAR.makeUnit(); 
Unit fatFish = UnitType.SPECIAL.makeUnit(); 

또 다른 방법은 Callable 개체입니다 :

public class Unit { 
    public enum UnitType { REGULAR, SPECIAL } 
    private Callable<Integer> additionFunc; 
    public Unit(UnitType type) { 
     switch (type) { 
     case REGULAR: 
      additionFunc = new Callable<Integer>() { 
       public Integer call() { 
        return 0; 
       } 
      }; 
      break; 
     case SPECIAL: 
      additionFunc = new Callable<Integer>() { 
       public Integer call() { 
        return 1; 
       } 
      }; 
      break; 
     } 
    } 
    public int swim() { 
     return additionFunc(); 
    } 
} 
1

한 가지 방법은 Unit의 유형에 대한 enumUnit 서브 클래스 함께 확장 및 공장 방법 :

공용 클래스 단위 {

public static Unit createUnit(UnitType type) { 
    if (UnitType.Special == type) { 
     return new Unit(type) { 
      @Override 
      public int swim() { 
       System.out.println("special swim"); 
       return 0; 
      } 
     }; 
    } 
    return new Unit(UnitType.Default); 
} 

private UnitType type; 

private Unit(UnitType type) { 
    this.type = type; 
    System.out.println("create unit for " + type); 
} 

public int swim() { 
    System.out.println("default swim"); 
    return 0; 
} 

public static void main(String[] args) { 
    Unit fish = Unit.createUnit(UnitType.Default); 
    Unit fatFish = Unit.createUnit(UnitType.Special); 
    fish.swim(); 
    fatFish.swim(); 

} 

}

이 간단한 형태의 열거입니다 :

공공 열거 UNITTYPE { 기본, 특별

}

2

당신의 문제에 대한 많은 솔루션이 있습니다. 그 중 하나는 상속을 사용하고, 기본 구현은 Unit 일 수 있으며, 원하는 메소드를 새로운 것으로 오버라이드 할 수 있습니다.

public class FatFish { 
    @Override 
    public void swim() { 
     // new behavior 
    } 
} 

또 다른 방법은 런타임에 알고리즘을 선택할 수있는 Strategy Design Pattern을 구현하는 것입니다 :

는 기본적으로 뭔가처럼 될 것입니다.

new Fish(new FatFishSwimStrategy()); 

또는 정상적인 행동

:

new Fish(new FishSwimStrategy()); 
+0

당신의 인터페이스'SwimStrategy'는'void execute()'대신에'void swim()'을 가져야한다고 생각합니까? –

+0

심지어 고마워. –