메소드에서 여러 개의 리턴 값을 리턴하는 방법 : 리턴 값을 나타내는 클래스 안에 메소드를 넣으십시오. 좋은 디자인입니까?


15

메소드에서 2 개의 값을 반환해야합니다. 내 접근 방식은 다음과 같습니다.

  1. 이 두 값을 유지하는 데 사용될 두 개의 필드로 내부 클래스를 만듭니다.
  2. 그 클래스 안에 메소드를 넣다
  3. 클래스를 인스턴스화하고 메소드를 호출하십시오.

메소드에서 변경 될 유일한 것은 결국 2 개의 값을 인스턴스의 필드에 지정한다는 것입니다. 그런 다음 해당 객체의 필드를 참조하여 해당 값을 지정할 수 있습니다.

좋은 디자인과 그 이유는 무엇입니까?


다른 옵션 (아마도 나쁜 옵션) : 참조하십시오 BitInteger[] java.math.BigInteger.divideAndRemainder(BitInteger val). 배열의 반환 값으로 2 개의 정수를 반환합니다.
earlNameless

반환하려는 두 값은 어떤 유형입니까?
Tulains Córdova

답변:


15

나는 다음 줄을 따라 이것을 주장 할 것이다.

  • 왜 메소드가 여러 값을 정확하게 반환합니까? 우리는 어떤 종류의 응집력에 대해 이야기하고 있습니다. 그 값은 실제로 단일 클래스의 필드 여야합니까, 아니면 동일한 방법으로 우연히 반환 되었습니까? 후자 인 경우 메서드를 두 가지 방법으로 나누는 것이 좋습니다. 편집 : 여기에 당신의 판단을 사용하십시오; 때로는 "동시"응집력의 유형이 최선의 선택 일 수 있습니다. 또 다른 옵션은 페어 또는 튜플 구문을 사용하는 것입니다. OOP에서는 일반적으로 공용 API에서는 볼 수 없습니다 (일부 주목할만한 예외는 표준 컬렉션 등).
  • 값이 클래스를 형성 할 가치가 있다면 내부 클래스를 사용하지 않는 것이 좋습니다. 내부 클래스는 일반적으로 외부에서 숨겨지는 내부 구현 세부 사항으로 사용됩니다. 이 결과가 "완전한"클래스가되어서는 안되는 이유가 있습니까?
  • 데이터를 보유하는 것 외에이 새로운 클래스에 어떤 작업이 적용됩니까? 객체 지향 디자인에서는 관련 데이터와 관련이있는 행동을 원합니다 (의도이기도합니다). 당신이 말하는 방법이이 수업에 살지 않겠습니까?

요약하자면,이 "데이터 객체"를 데이터와 행동을 모두 포함하는 본격적인 클래스로 바꿀 수 있는지 알 수있을 것입니다. 추가 설명으로 상태가 한 번 설정되므로 클래스를 변경할 수 없게 할 수 있습니다. 불변으로 설정하면 잘못 설정되거나 나중에 수정되는 것을 방지하는 데 도움이됩니다 (예 : 필드 중 하나를 null로 설정하고 전달 함).

편집 : Patkos Csaba가 올바르게 지적했듯이 여기에 적용되는 원칙은 단일 책임 원칙입니다 ( SRP )입니다. 만들려는 클래스에는 실제로 하나의 책임이 있어야합니다 ( 변경 이유 ). 이 설계 지침은 두 필드가 단일 클래스에 속하는지 여부를 파악하는 데 도움이됩니다. Wikipedia 예제를 고수하기 위해 클래스는 보고서 유형으로 간주 될 수 있으며,이 경우 SRP를 준수하지만 추가 정보 없이는 설명하기가 어렵습니다.


이 답변의 일반적인 아이디어에 동의하지만 밀접하게 관련된 두 개의 데이터 조각이 함께 계산되는 합법적 인 경우가 있지만 프로그램의 다른 곳에서 서로 묶는 것은 의미가 없습니다. 이러한 경우와 같은 것을 반환하기에 충분히 깨끗할 수 있습니다 Pair<OneClass, AnotherClass>. 어떤 사람들은 동의하지 않을 것 입니다. 어쨌든 Pair구현 세부 사항이어야하며 공개 API 메소드에 나타나지 않아야합니다.
9000

@ 9000 동의합니다. 나는 실제로 단어 가이 경우 문자 그대로 고려 되는 것을 의미했습니다 . 즉, 방법을 나누는 것이 항상 최선의 해결책은 아니지만 그 방향의 대략적인 표시 일뿐입니다. 그 줄을 따라 편집하겠습니다.
Daniel B

1
좋은 대답입니다. 내가 추가 할 유일한 것은 SRP (Single Responsibility Principle) ( en.wikipedia.org/wiki/Single_responsibility_principle )에 대한 참조입니다. 이 옵션을 선택하면 논의중인 방법이 SRP에 대한 단순한 위반 일뿐 아니라 분할이 간단한 솔루션 일 가능성이 큽니다. 내 경험상, 메소드가 2 개 이상의 값을 반환하려고 할 때마다 90 %의 경우 2 개의 메소드가 있거나 다른 클래스를 추출해야합니다.
Patkos Csaba

@PatkosCsaba 감사합니다. 포함하도록 수정했습니다. 나는 일반적으로 커플 링과 응집력 측면에서 설명하는 것을 고수하지만 SOLID 원리는 오늘날까지 살아가는 기본 규칙으로 간주됩니다.
Daniel B

@DanielB : SOLID를 더 높은 수준으로보고 개념을 이해하기가 더 쉽습니다. 커플 링과 응집력은 여전히 ​​기본이지만 더 낮은 수준입니다. SOLID는 커플 링과 응집력을 잘 활용하여 원리를 설명하고보다 일반적인 수준으로 제시합니다.
Patkos Csaba

10

Python과 같은 다른 언어로 제공되는 Tuple의 개념이 있습니다.

쉽게 재사용 할 수있는이 일반화 된 클래스의 인스턴스를 반환 할 수 있습니다.

public class TypedTuple<L, R> implements Serializable {
private static final long serialVersionUID = 1L;

  protected L left;
  protected R right;

  protected TypedTuple() {
    // Default constructor for serialization
  }

  public TypedTuple(L inLeft, R inRight) {
    left = inLeft;
    right = inRight;
  }

  public L getLeft() {
    return left;
  }

  public R getRight() {
    return right;
  }
}

2
create()생성자에서 형식 매개 변수를 지정하지 않아도되도록 일반적인 정적 메서드 를 사용하는 것이 좋습니다. 또한이 클래스의 이름 은 2 튜플의 값만 나타낼 수 있기 때문에 Pair대신 클래스 이름을 Tuple지정합니다.
augurar

5

이 수업은 다른 수업에서 책임을지고있는 것으로 보이며,이 디자인이 훌륭하지 않다고 생각합니다.

다중 값을 반환하는 메서드의 경우 오히려

  • 반환 값을 포함하는 일반 포함 자 (예 : 목록 또는 맵)를 반환합니다.

또는

  • 필요한 필드 + getter + 모든 필드가있는 생성자 만 포함하는 반환 값에 대한 클래스를 만듭니다.

두 번째 옵션의 예 :

public Class FooBarRetval {
   private String foo;
   private int bar;

   public FooBarRetval (String foo, int bar) {
      this.foo = foo;
      this.bar = bar;
   }

   public String getFoo() {
      return foo;
   }

   public int getBar() {
      return bar;
   }
}

필드를 공개하면 값을 개별적으로 변경하는 옵션이 추가되지만 값은 분명히 관계가 있습니다 (그렇지 않으면 동일한 방법으로 반환하지 않아도 됨). 이 특별한 상황에서는이 패턴을 사용하지 않는 것이 좋습니다. 그러나 요점은 공공 속성과 개인 속성에 대한 토론은 OPs 질문과 관련이 없으며 다른 좋은 대답으로 마지막 문장에 대한 이유가 없다는 것입니다.
scarfridge

첫 번째가 선호되어야합니다.
Juanin

scarfridge : 점을 찍고 마지막 문장을 제거했습니다.
user281377

2
접근 자와 시간을 낭비 할 이유없이 공개 최종 필드 만 사용하십시오.
augurar


0

짧은 대답 : 두 값으로 배열이나 목록을 반환 할 수 있습니다.

나는 개인적으로 다음과 같은 두 가지 방법을 쓸 것입니다.

int x = obj.getX();
int y = obj.getY();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.