메서드 매개 변수 대신 생성자에 데이터를 전달할 때 클래스 개념이 어떻게 변경됩니까?


12

파서를 만들고 있다고 가정 해 봅시다. 한 가지 구현은 다음과 같습니다.

public sealed class Parser1
{
    public string Parse(string text)
    {
       ...
    }
}

또는 대신 텍스트를 생성자에 전달할 수 있습니다.

public sealed class Parser2
{
    public Parser2(string text)
    {
       this.text = text;
    }

    public string Parse()
    {
       ...
    }
}

두 경우 모두 사용법이 간단하지만 다른 것에 비해 매개 변수 입력을 활성화 한다는 것은 무엇을 의미Parser1 합니까? API를 볼 때 동료 프로그래머에게 어떤 메시지를 보냈습니까? 또한 특정 경우 기술적 장점 / 단점이 있습니까?

두 번째 구현에서 인터페이스가 의미가 없다는 것을 알게되면 또 다른 질문이 나타납니다.

public interface IParser
{
    string Parse();
}

... 첫 번째 인터페이스가 적어도 어떤 목적으로 사용될 수있는 곳. 이것은 클래스가 "인터페이스 가능"인지 아닌지를 의미합니까?


OO의 의미가 실제로 의도를 표현하는 방법에 대한 유용한 Q & A를 처음 보았습니다. 지금까지 그것은 모두 나에게 구문 설탕이었다.

답변:


11

의미 적으로 말하자면, OOP에서는 클래스를 빌드하는 데 필요한 매개 변수 집합 만 생성자에 전달해야합니다. 마찬가지로 메서드를 호출 할 때 비즈니스 논리를 실행하는 데 필요한 매개 변수 만 전달해야합니다.

생성자에 전달해야하는 매개 변수는 합리적인 기본값이없는 매개 변수이며 클래스가 변경 불가능한 경우 (또는 실제로는 a struct) 기본이 아닌 모든 기본 특성을 전달해야합니다.

두 가지 예와 관련하여 :

  • text생성자에 전달 Parser2하면 나중에 해당 텍스트 인스턴스를 구문 분석하기 위해 클래스가 특별히 빌드 됨을 암시합니다 . 특정 파서가 될 것입니다. 일반적으로 클래스 작성이 매우 비싸거나 미묘한 경우에는 RegEx가 생성자에서 컴파일 될 수 있으므로 인스턴스를 보유한 후에는 컴파일 비용을 지불하지 않고도 재사용 할 수 있습니다. 또 다른 예는 PRNG를 초기화하는 것입니다. 거의 수행하지 않는 것이 좋습니다.
  • text메소드에 전달 하면 Parser1호출로 다른 텍스트를 구문 분석하기 위해 재사용 할 수 있음을 알립니다 .

3
Parser1이 상태를 유지한다는 약한 신호가 있다고 덧붙였습니다. 즉, 특정 텍스트 문자열이 이전에 tat 인스턴스에서 수행 된 결과에 따라 다른 결과를 생성 할 수 있습니다. 반드시 그런 것은 아니지만, 그럴 수도 있습니다.
jmoreno

8

자, 변수를 생성자 매개 변수로 전달하는 것이 무엇을 의미하는지 기억해 봅시다. 객체의 메소드에서 인스턴스 변수를 사용하기 위해 객체를 초기화합니다. 요점은 수업에서 높은 응집력 을 원하기 때문에 둘 이상의 방법으로 사용하고 싶을 것입니다 .

메소드에 직접 매개 변수를 전달한다는 것은 오브젝트에 메시지를 보내고 응답을받는 방식을 의미합니다. 이를 통해 고객은 객체가 자신에게 서비스를 제공하기를 원합니다.

결론적으로, 이들은 매개 변수를 전달하는 두 가지 매우 다른 수단이므로 개체가 내부적으로 일부 정보를 관리하면서 서비스를 제공하거나 일부 기능을 제공해야하는지 여부를 선택해야합니다.


+1. 응집력은 그것이 메소드 또는 생성자에 속하는지 결정하는 방법입니다.
jhewlett

4

두 경우 모두 사용법이 간단하지만 다른 것에 비해 Parser1에 대한 매개 변수 입력을 활성화한다는 것은 무엇을 의미합니까?

근본적인 디자인 변화입니다. 그리고 디자인은 의도와 의미를 전달해야합니다. 구문 분석하려는 모든 문자열에 대해 별도의 객체가 필요합니까? 다시 말해, 왜 우리는 stringX를 가진 파서 인스턴스와 stringY를 가진 다른 인스턴스가 필요한가? 파싱과 두 사람이 함께 살고 죽어야하는 주어진 문자열은 무엇입니까? 로버트 하비 (Robert Harvey)가 말한 것처럼 "기본적인 파싱 (parsing)"구현이 바뀌지 않는다고 가정하면 아무런 의미가없는 것 같습니다. 그리고 심지어 의심스러운 IMHO.

메서드 매개 변수 대신 생성자에 데이터를 전달할 때 클래스 개념이 어떻게 변경됩니까?

생성자 매개 변수는 객체에 필요한 것들을 알려줍니다. 이러한 상태가 없으면 적절한 상태를 보장 할 수 없습니다. 또한 한 파서가 다른 파서와 근본적으로 어떻게 다른지 알고 있습니다.

생성자 매개 변수를 사용하면 클래스 사용 방법에 대해 너무 많이 알 필요가 없습니다. 대신 특정 속성을 설정 해야하는 경우 어떻게 알 수 있습니까? 벌레의 전체 캔이 열립니다. 어떤 속성? 어떤 순서로? 어떤 방법을 사용하기 전에? 등등.

두 번째 구현에서 인터페이스가 의미가 없다는 것을 알게되면 또 다른 질문이 나타납니다.

API에서와 같이 인터페이스는 클라이언트 코드에 노출되는 메서드 및 속성입니다. public interface { ... }독점적으로 포장하지 마십시오 . 따라서 인터페이스 의 의미 는 생성자 대 메서드 매개 변수 딜레마, NOT public interface Iparserpublic sealed class Parser

sealed클래스는 홀수이다. 다른 파서 구현에 대해 생각하고 있다면- "Iparser"에 대해 언급했다. 상속은 나의 첫 번째 생각이다. 내 생각에 자연스럽게 확장 된 개념 일뿐입니다. IE는 모두 ParserX기본적으로 Parser입니다. 다른 표현으로는? ... 독일 셰퍼드는 개 (상속)이지만, 앵무새에게 나무 껍질을 훈련시킬 수 있습니다 (개처럼 행동- "인터페이스"). 그러나 폴리는 개가 아니며, 단순한 척하면서 개의 하위 집합을 배웠습니다. 추상적이든 그렇지 않든 클래스는 인터페이스 역할을 완벽하게 수행합니다 .


파서처럼 걷고 파서처럼 말하면, 오리입니다!

2

클래스의 두 번째 버전은 변경할 수 없습니다.

인터페이스는 여전히 기본 구현을 교체 할 수있는 기능을 제공하는 데 사용될 수 있습니다.


기능적인 방식으로 클래스 내에서 데이터를 전달하여 첫 번째 버전에서도 불변으로 만들 수 없습니까?
ciscoheat

2
물론. 그러나 불변성의 일반적인 패턴은 생성자를 사용하여 클래스 멤버를 설정하고 읽기 전용 속성을 갖는 것입니다. 함수형 프로그래밍에는 클래스가 필요하지 않습니다.
Robert Harvey

실라와 샤를 디스 : OO 또는 불변 데이터를 선택합니까? 나는 그것이 그런 식으로 들었다는 것을 들어 본 적이 없다.

2

파서 1

기본 생성자를 사용하여 입력 텍스트를 메서드에 전달하면 Parser1을 재사용 할 수 있습니다.

파서 2

입력 텍스트를 생성자에 전달하면 각 입력 문자열에 대해 새 Parser2를 작성해야합니다.


물론, 다음 단계로 넘어 가면 재사용 할 수없는 대상과 비교하여 재사용 가능한 대상에 대해 결론을 내릴 수있는 것은 무엇입니까?
ciscoheat

나는 그 이상을 가정하지 않고 대신 문서화를 연기합니다.
Mike Partridge 2016 년

아이덴티티가 변경되는 "재사용 가능한 객체"는 안전하지 않습니다. 또한 관리되는 프레임 워크를 사용하면 물건을 버릴 필요가없고 덮어 쓰거나 범위를 벗어날 필요가 없습니다. 멀리 건설하십시오!
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.