2012-11-15 3 views
3

자바의 메소드 범위 내에서 유형 변수를 도입 할 수 있는지 궁금합니다. 즉, 메소드 본문 내에서 범위를 제한합니다.Java에서 범위가 제한된 유형 변수

그러나 추상적 인 문제를 설명하려고 시도하는 것이 아니라 구체적인 문제를 설명합니다.

public class Settings { 
    public static abstract class Setting<T> { 
     public T value; 
     public abstract T fallbackvalue(); 
    } 

    private final List<Setting<?>> settings; 
} 

내가 지금은 추상적 인 방법에 의해 제공되는 그들의 대체 값으로 모든 설정 값을 설정, Settings에서, 함수를 작성하려면 : 나는 조금 같이 클래스의 몇 가지있다. 내 첫 번째 생각은 이렇게 할 것입니다 :

public void reset() { 
    for(Setting<?> setting : settings) 
     setting.value = setting.fallbackvalue(); 
} 

그러나 두 번째 생각에서 이것이 작동하지 않는 이유는 분명합니다. setting.value에 대한 <?>의 캡처는 setting.fallbackvalue()의 캡처와 다릅니다. 어거, 캡처를 통합하는 방법이 필요해. 그것은 다음과 같이 그것을 해결하기 위해 이다

private static <T> void reset1(Setting<T> s) { 
    s.value = setting.fallbackvalue(); 
} 

public void reset() { 
    for(Setting<?> setting : settings) 
     reset1(setting); 
} 

명시 적 유형 변수 reset1에 대한 <T> 편리하게 캡처를 통합,하지만 분명히 네임 스페이스를,이 기능을 소개하는 오염 수있는 세계에서 가장 추악한 일이의 난장판 형식 시스템을 만족시키기 위해 코드를 쉽게 읽을 수 없게 만듭니다.

reset의 본문 내에서이를 수행 할 방법이 없습니까?

public void reset() { 
    for(Setting<?> setting : settings) { 
     <T> { 
      Setting<T> foo = setting; 
      foo.value = foo.fallbackvalue(); 
     } 
    } 
} 

그것은 세계에서 가장 예쁜 것은 아니지만, 적어도 내 눈이 훨씬 덜 strainful 위의 변형보다 : 내가 뭘하려는 것은 단순히이 같은 것입니다. 아아, 불가능합니다. 그러나 가능한 무엇이, 그 후에?

답변

2

아니요

와일드 카드 캡처는 새로운 유형 변수를 도입하지만 컴파일러에서만 사용할 수 있습니다. 프로그래머가 직접 액세스 할 수있는 방법은 없습니다.

현재 클래스/메소드 만 유형 변수를 도입 할 수 있습니다. 따라서 와일드 카드없이 형식에 와일드 카드 표현 형식을 변환 할 수있는 유일한 방법은 reset1 일이 일반적으로 인정되는

+0

나는 당신이 옳다는 것을 인정해야 할 것이 두렵습니다. 문제를 해결하기위한 일반적인 방법으로 일반적으로 "reset1"방법을 제안하는 것 같습니다. 유감 이네요. – Dolda2000

3

코드의 다른 측면을 변경하지 않고도 원하는 것을 할 방법이 없습니다. 그러나 (특정 문제를 해결하기 위해), 당신은 내부 Setting 클래스의 reset 방법을 쓸 수 있습니다 :합니다 (Settings 클래스의 reset 방법)

다음
public void reset() { 
    value = fallbackvalue(); 
} 

루프를 간단하게 다음과 같습니다

for (Setting<?> setting : settings) 
    setting.reset(); 
+0

확실히, 'reset1' 함수와 기본적으로 같으며'Settings.reset'의 내부 구현 세부 사항 외의 용도로는 사용되지 않습니다. 어느 쪽이든, 저는 타입 캡쳐 관리의보다 일반적인 문제에 관심이 있습니다. – Dolda2000

+0

@ Dolda2000 그렇습니다. * 기본적으로 *'reset1'이지만 더 논리적 인 장소에 있습니다. 궁극적으로, 나는 이것이 가장/가장 깨끗한/가장 쉬운 관리/가장 읽기 쉬운 솔루션이라고 생각합니다. 또한 다른 방법으로 문제를 해결할 수 있는지 확신 할 수 없습니다 (하지만 잘못되었을 수도 있습니다 - 이전에 발생했습니다). 지나치게 복잡하지 않은 방식 (예 : 코드의 다른 측면에 대한 변경을 요구하지 않음)을 생각하면 내 대답을 업데이트해야합니다. – arshajii

+0

틀림없이 문제는 OPC에서 예시 된 개념을 어떻게 적절하게 모델링 할 것인가가 아니라 유형 캡쳐 관리에 관한 것입니다. ;) – Dolda2000

1

(본질적으로 동일한 메커니즘 또는 다이아몬드 추론 new Foo<>(setting)와 생성자) 방법을 통해 표현을 전달하는 것입니다 그것을하는 방법. 이것은 "캡처 도우미"라고하며 제네릭에서 자주 인용되는 패턴입니다. 그것은 일반적으로 다음과 같은 상황에서 오는 :이 경우

public void swap(List<?> list, int i, int j) { // swap elements i and j of the list 
    // how to write? 
} 

, 당신은 파라미터 화 된 형태의 무언가를 얻고, 해당 유형의 다시 뭔가를 넣어 둘 필요가있다.와일드 카드만으로는 그렇게 할 수 없습니다. 이것은 여러분의 경우와 같습니다. 여러분이 무언가를 얻고 무언가를 넣고 있기 때문입니다. 우리는 그 유형이 동일해야만한다는 것을 압니다. 그러나 와일드 카드는 너무 약해서 그것을 강요합니다. 만 명시 적 타입 변수는 우리가 그것을 할 수 있도록 할 수 있습니다

public <T> void swap(List<T> list, int i, int j) { 
    T tmp = list.get(i); 
    list.set(i, list.get(j)); 
    list.set(j, tmp); 
} 

그러나, 우리는 인수 목록에서 하나의 장소에서 사용이 외부 <T>을 원하지 않는다. 바깥 세상에는 swap(List<?> list, int i, int j)가 잘 작동합니다. 이 <T> 형식 매개 변수를 사용해야한다는 것은 아무도 알 필요가없는 구현 세부 사항입니다.

private <T> void swap_private(List<T> list, int i, int j) { ... } 
public void swap(List<?> list, int i, int j) { 
    swap_private(list, i, j); 
} 

그것은 낭비를 보인다,하지만 그것이 방법 : 그래서 그것을 숨기기 위해, 우리는 와일드 카드를 취하는 기능을 일반적인 기능을 포장.

상황과이 상황의 유사한 상황과 캡처 도우미가이 상황의 표준 솔루션이라는 사실을 감안할 때 나는 더 나은 방법이 없다고 자신있게 말할 수 있습니다.