메소드 오버로드는 언제 적절한가요?


10

기존의 합리적으로 큰 시스템을 작업 중이라고 가정합니다. myObject클래스 의 객체가 있습니다 MyClass(예를 들어 Java로 작업한다고 가정). myObject는 a Collection, List및 (필자가 생각하는) 관련이없는 다른 객체를 포함하는 구성 입니다. 여기에는 노출되지 않았 List는지 확인하기 위해 구성 된 메소드를 호출하는 데 사용되는 대리자 메소드가 포함되어 있습니다 List(내 용어가 잘못되어서 죄송합니다).

이제이 있다고 가정 해 봅시다 List입니다 List<String>어떤 이유로, 주요 접근 방법은 클래스에 대한 마스크 방법이지만 SomeOtherClass. 에 새로운 값 쌍을 삽입 List하려면 SomeOtherClass이라는 객체가 someObject있습니다. 내가 호출 myObject.insert(someObject)하고 insert메서드 안에 String에 넣을 검색하는 마술이있을 것 List<String>입니다.

지금은 만 가지고 있다고 가정하면 String값을, 어떤 SomeOtherClass객체가 삽입 없습니다. insert이 시스템의 모든 것을 손상 시킬 수 있기 때문에 메소드를 수정할 수 없다고 가정 합니다. 그런 다음 insert메서드를 오버로드해야 합니까? 아니면 SomeOtherClass전화 할 때마다 새 객체를 만들어야 insert합니까?

과부하가 걸리면 다음과 같이 보일 것입니다 ...

public void insert(String s) {
    ...
}

public void insert(SomeOtherObject obj) {
    this.insert(obj.magicStringMethod());
}

(이 예제는 어제 발생한 과부하와 관련하여 비슷한 (약간 더 복잡한) 상황을 기반으로 고안된 퍼즐입니다. 불분명 한 것이 있으면 확장하겠습니다.)

메소드를 오버로드하기에 적합한 장소입니까? 그렇지 않은 경우 언제 메소드에 과부하를 주어야합니까?


Java를 가정 할 때이 문제를 해결하기 위해 Generics를 사용하는 방법을 살펴 보셨습니까? 내가 정말로 묻는 것은 문자열이 실제로 무엇을 나타내는 것 같아요? 실제로 실제 도메인 객체를 나타내는 경우이 문제를 해결하는 또 다른 잠재적 인 방법이 있습니다
Martijn Verburg

@MartijnVerburg이 단계에서는하지 않았습니다. 저는 인턴 일 뿐이므로 디자인 패턴과 같은 것에 익숙하지 않으며 아직 좋은 디자인 습관을 가지고 있지 않습니다. 두 번째 질문에 대한 답으로 실제 도메인 개체를 나타냅니다. magicStringMethod()필자의 예 에서는 도메인 개체 인 String표현을 얻습니다 SomeOtherObject.
blahman

가능하면 과부하가 걸리지 않는 것이 좋습니다. 때때로 혼란을 야기합니다. 디자인 타임에 호출 된 메소드를 확신하는 것이 가장 좋습니다. 다음을 참조하십시오 : programmers.stackexchange.com/questions/132369/…
NoChance

답변:


7

다른 유형을 지원하려는 경우 과부하가 발생합니다.

public overload void MyMethod(int value)
{ 
}

public overload void MyMethod(bool value)
{
}

public overload void MyMethod(string value)
{
}

또는 다른 매개 변수 목록을 사용하여 점진적 인터페이스를 지원하려면 :

public overload void MyOtherMethod()
{
    this.MyOtherMethod(DefaultValue);
}

public overload void MyOtherMethod(int value)
{
    this.MyOtherMethod(value, DefaultOtherValue);
}

public overload void MyOtherMethod(int value, bool otherValue)
{
    ...
}

약간 미쳐서 다른 유형과 점진적 인터페이스를 모두 지원할 수도 있지만 오버로드 된 메소드 간 동작에 변화가 생기는 것을 피해야한다는 점을 명심해야합니다. 각 오버로드 된 메소드는 오버로드 된 그룹의 다른 메소드와 기능적으로 동일해야합니다. 그렇지 않으면 동작이 어떻게, 언제 또는 왜 변경되는지에 대해 명확하지 않습니다. 두 함수가 완전히 다른 것을 수행하려면 적절하게 이름을 지정해야합니다.


7

두 방법이 의미 적으로 동일 할 때 오버로드가 적절하다고 말하고 싶습니다. dukeofgaming의 예를 훔치려면 :

이들은 적절하게 오버로드됩니다.

public int sum(int a, int b){
    return a+b;
}

public double sum(double a, double b){
    return a+b;
}

이것들은 아닙니다 :

public int sum(int a, int b){
    return a+b;
}

public double sum(double a, double b){
    return a-b;
}

그것은 극단적 인 예입니다 (잡지 않으면 마지막 방법은 실제로 추가 대신 뺍니다). 같은 아이디어를 가진 클래스에 여러 개의 메소드가있는 경우 일관성있게 행동해야한다는 아이디어입니다.

귀하의 예에서 주어진 정보에서 정보는 동등한 것으로 보이며 (하나는 다른 것부터 호출하기 때문에) 과부하 된 것이 합리적이라고 생각합니다. 메서드를 추가해야하는지 확실하지 않은 경우 팀의 상급자에게 물어 보는 것은 아프지 않지만 추가 한 경우 동일한 이름을 사용합니다 (예 : 과부하).


1
답변 해주셔서 감사합니다. 나는 더 선배에게 물어 봤지만 코드가 다소 흥미로운 상태이기 때문에 그들의 솔루션은 내가 확신하지 못했지만 그럼에도 불구하고 구현되었다 (오버로드가 아님).
blahman

5

기본적으로 메소드의 매개 변수가 메소드의 작동 방식을 결정하도록합니다.

간단한 예는 다음과 같습니다.

class Calc{
    //...
    public int sum(int a, int b){
        return a+b;
    }
    public double sum(double a, double b){
        return a+b;
    }
    //...
}

메소드 sum (a, b)에 몇 개의 정수를 전달하면 메소드 호출이 메소드 서명과 일치하므로 (즉, double sum (double, double)은 작동하지 않으므로 첫 번째 구현을 호출해야 함을 알고 있습니다. 합계 방법 두 정수).

호출의 서명은 사용 가능한 구현과 일치해야하므로 sum (string, string)을 호출하려고 시도하면 다음과 같은 경우가 아니면 작동하지 않습니다.

class Calc{
    //...
    public int sum(int a, int b){
        return a+b;
    }
    public double sum(double a, double b){
        return a+b;
    }
    public string sum(String a, String b){
        return "" + (Double.parseDouble(a) + Double.parseDouble(b));
    }
    //...
}

tl; dr : 같은 이름의 메소드에 제공하는 매개 변수에 따라 클래스가 올바른 메소드를 처리하도록하십시오.

상속 할 때이를 재정의라고합니다.

이 다른 시나리오의 좋은 예는 클래스를 상속하여 클래스의 기본 동작을 변경하고 싶을 때, 특히 템플릿 메소드 패턴 과 비슷한 것이 있는데 , 여기에는 메소드에 구현 된 일부 알고리즘의 각 단계가 있습니다.

서로 호출하는 ... class Robot라는 메소드 가 있다고 상상해보십시오 . 또한 Robot 클래스의 객체 만 추가 할 수있는 robot_army라는 컬렉션이 필요합니다. 로봇은 기본적으로 방법 에 따라 기관총을 발사 합니다.fireAtTarget(Target target)fireWeaponA(target); fireWeaponB(target); fireWeaponC(target);fireWeaponX()

그럼 당신은 갖고 싶어 class LazorRobot하고 class MissileRobot당신이? 다시 한번 로봇을 구현 아니, 단지 LazorRobot 및 MissileRobot 상속 로봇이 있고, 않으며, 과부하 각각 fireWeaponX()사용 lazorz 또는 미사일 방법을 당신이 다시 구현할 필요없이 서로 다른 무기와 같은 동작을합니다 나머지 방법.

tl; dr : 메소드의 동작이 인터페이스를 깨지 않고 클래스에 의존하도록하십시오 (robot_army는 Robot 만 허용하지만 Robot을 상속하는 모든 클래스는 확장으로 허용합니다).


첫 번째 예는 재정의 입니다. 메소드의 인터페이스를 유지하면서 자손의 동작을 변경하십시오. 그 의미는 대체 방법을 제공하지 않으려는 것입니다. 그러나 두 번째 예는 올바르게 과부하입니다. 오버라이드 시점과 과부하 시점을 강조하려는 의도라면 답을 명확하게하고 싶을 수도 있습니다. 그렇지 않으면 전체 when inheriting섹션이 필요하지 않을 수 있습니다. :)
S.Robins 2012

Derp, 카페인은 이번에 = P를 얻었고, 두 번째 부분은 첫 번째로 두 번째 부분은 일반적인 관심사로 두었습니다. 수정 해 주셔서 감사합니다.
dukeofgaming 2013

내가 제대로 대답을 이해한다면, 나는 나를 말, 사이에 동작의 차이를 추론 할 수있는 매개 변수를 볼 때에만 과부하,해야 sum(String, String)하고 sum(int, int)?
blahman

@blahman 당신은 다른 유형, 유형의 혼합을 사용하거나 추가 매개 변수를 추가 할 때 과부하해야합니다. 오버로딩은 param = value 기본 구문이 지원되지 않는 기본 매개 변수로 메소드를 작성하는 방법을 제공합니다 . 내 말의 의미를 확인하려면 대답을 참조하십시오.
S.Robins

1
@ blahman BTW 및 다른 주제에 대해 너무 많은 매개 변수가 있고 일부 매개 변수가 선택 사항 인 경우 모든 기본값을 가진 단일 개체 또는 데이터 구조를 보내는 것이 더 좋으므로 해당 개체 또는 데이터의 특성을 변경하는 것이 좋습니다 구조. 이렇게하면 매번 단일 매개 변수를 추가하기 위해 동일한 메소드의 20 가지 버전을 만들 필요가 없습니다.
dukeofgaming
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.