2009-05-14 4 views
6

그래서 내가 가진 값을 설정하는 클래스 내의 필드 또는 속성을 사용해야합니다나는 코드의 조각을 통해 동료와의 친선 인수에

public sealed class NewObject 
{ 
    private string _stuff = string.Empty; 

    public string Stuff 
    { 
     get { return GetAllStuff(); } 
    } 

    private string GetAllStuff() 
    { 
     //Heavy string manipulation of _stuff 
    } 

    public NewObject(string stuffToStartWith) 
    { 
     _stuff = stuffToStartWith; 
    } 

    public static NewObject operator +(NewObject obj1, NewObject obj2) 
    { 
     if (obj1 == null) 
      throw new ArgumentNullException(); 

     if (obj2 == null) 
      throw new ArgumentNullException(); 

     NewObject result = new NewObject(string.Empty); 
     result._stuff = String.Concat(obj1._stuff, obj2._stuff); 

     return result; 
    } 
} 

인수는 연산자 재정의 이상이었다. 공동 작업자는 생성자가 아닌 사적인 필드의 값을 설정하는 것이 최상의 프로그래밍 방법은 아니라고 생각합니다. 동료가 제안한 해결책은 Stuff 속성의 이름을 AllStuff으로 리팩토링하고 getset 접근자를 가진 속성 Stuff을 추가하고 연산자 오버라이드에 새로운 Stuff 속성을 사용하는 것입니다. 보이게하기 :

public static NewObject operator +(NewObject obj1, NewObject obj2) 
    { 
     if (obj1 == null) 
      throw new ArgumentNullException(); 

     if (obj2 == null) 
      throw new ArgumentNullException(); 

     NewObject result = new NewObject(string.Empty); 
     result.Stuff = String.Concat(obj1.Stuff, obj2.Stuff); 

     return result; 
    } 

나는 동의하지 않는다. 나는 속성이 클래스 밖에서 읽기 전용으로 유지되기 때문에 첫 번째 방법이 더 좋다고 느낍니다. 내 질문은 개체 지향 디자인의 가장 좋은 방법은 어떤 방법입니까?

답변

7

속성에 private set을 부여 할 수 있습니다 (속성 구문을 사용할 수 있도록 허용하면서 가시성 또는 부족함을 유지할 수는 있지만).

클래스 내에서 변수는 공정한 게임이라고합니다. 상속 된 클래스를 포함한 외부의 어느 곳에서나 속성은 getset이어야하지만 선언 클래스에서는 private 멤버를 할당해도 괜찮습니다.

2

당신은

잘못을 ... 정교 맞아, 개인 변수는 당신이 당신으로하십시오 할 수 있습니다. 누군가 당신 (특히 +와 같은 것)의 값을 변경하는 조작을하면 생성자 바깥의 값을 수정하는 데 아무런 문제가 없습니다. 그 모든 것이 사적인 것 같아.

당신이 원하는하지 않는 한 그것은 불변 ...

업데이트
이 더 많은 내가 그것에 대해 생각, 더 나는 당신의 동료 '일정'사람과 '개인'변수를 혼란 생각 - 혹은 두 개념을 병합합니다. 개인 변수가 객체의 수명 내내 동일하게 유지되어야하는 이유는 없습니다. 이는 친구가 암시하는 것으로 보이는 것입니다. const는 변함이 없으며 private은 객체만을위한 것이고 두 개의 매우 다른 패턴입니다.

갱신 2 또한
는 개체 그냥 문자열보다가 갑자기 경우, 그의 디자인은 떨어져 폭포 -와 변수는 숯불 *과는 len 문자열 객체의 생각 (얽혀 있고,해야합니다 함께 유지). 마지막으로 사용자가 원하는 것은 객체의 내부 변수를 처리해야한다는 것입니다. 객체를 객체로 만들고 자체 내부 값을 유지하고 단일 엔터티를 사용자에게 제공합니다.

+0

@ cyber : 나는 이것이 OP의 문제가 아니라고 생각한다. 그의 동료가 생성자 또는 속성 구현 외부에서 직접 개인 변수를 변경하지 않겠다는 옹호자처럼 나에게 들렸다. 나는 그가 물체의 삶에 대해 같은 가치를 지키라고 옹호했다고 생각하지 않는다. –

1

나는 그의 접근 방식의 이점이 무엇인지 알지 못합니다.

0

나는 personaly public 읽기 전용 속성을 갖고 싶어 그러므로 내가 자동으로 구현 private 속성 대신 private 필드와 public-getprivate-set 속성을 사용하여, 전혀 분야가없는 것을 선호합니다.
속성에 코드를 추가해야한다면 속성 접근 자 내부의 필드 만 사용하고 생성자를 포함하여 getters 및 setters를 사용합니다.
readonly 필드가 필요하면 필드도 사용해야하지만 C# 4.0에서는 읽기 전용 속성이 도입됩니다.


다음 코드를 사용하면 전체적인 문제를 피할 수 있습니다.

public static NewObject operator +(NewObject obj1, NewObject obj2) 
{ 
    return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff)); 
} 

내 선호 구현은 다음과 같이 될 것이다.

public sealed class NewObject 
{ 
    private String Stuff { get; set; } 

    // Use a method instead of a property because the operation is heavy.  
    public String GetAllStuff() 
    { 
     // Heavy string manipulation of this.Stuff. 
     return this.Stuff; 
    } 

    // Or lets use a property because this.GetAllStuff() is not to heavy. 
    public String AllStuff 
    { 
     get { return this.GetAllStuff(); } 
    } 

    public NewObject(String stuffToStartWith) 
    { 
     this.Stuff = stuffToStartWith; 
    } 

    public static NewObject operator +(NewObject obj1, NewObject obj2) 
    { 
     // Error handling goes here. 

     return new NewObject(String.Concat(obj1.Stuff, obj2.Stuff); 
    } 
} 
+0

"읽기 전용 속성"이 의미하는 바를 오해하고 있습니까? 지금은 setter없이 속성을 코딩하여 읽기 전용으로 만들 수 있습니다 ... –

2

일반적인 문제는 계약 정책과 관련이 있습니다.

(public set) 속성의 개념은 호출 될 때 상태 변경의 의미 개념 외에도 다른 동작이 취해질 수 있다는 것입니다. 예를 들어, setter를 호출하면 이벤트가 발생하거나 주변 장치가 트리거 될 수 있습니다.

귀하의 직장 동료는이 부동산을 사용하지 않으면 계약을 밟고있어 이벤트가 실행되지 않는다고 말하고 있습니다. 그래서 여기

당신이보기 당신의 동료의 관점에서해야입니다 : 이제

this.Prop = CalculateSomeValue(); 
if (this.Prop < kPropMin) { 
    this.Prop = kPropMin; 
} 
else if (this.Prop > kPropMax * 2) { 
    this.Prop = kPropMax * 2; 
} 
this.Prop = this.Prop/2; 

, 이것은 인위적인 경우가 있지만, 난 그냥 GET 세 번에 가능한 헤비급 속성을 띄워 최대했습니다 세트에서 3 번, 그 중 하나는 불법 일 수 있습니다 (kHighLimit/2로 설정). 로컬을 사용하고 끝에 한 번 정확하게 세트를 호출하여이 문제를 해결할 수 있습니다. 그래도 나는 들판을 뒤집어 쓰고 싶다.

더 나은 접근 방법은 실용적으로 취하는 것입니다 : 클래스의 속성을 사용하십시오. 세트 또는 get의 모든 부작용을 호출하려는 경우에만 사용해야하며, 그렇지 않으면 속성의 정신을 대신 따르십시오.

- 설명 - 으로는의 내 설정 속성은 다음과 같습니다 가정 해 봅시다, 재산의 정신을 준수 : 나는 그런 많은 세부 사항을 고려했습니다이에서

bool PropValueOutOfRange(int val) { 
    return val < kPropMin || val > kPropMax; 
} 

public int Prop { 
    set { 
     if (PropValueOutOfRange(value)) 
      throw new ArgumentOutOfRangeException("value"); 
     if (PropValueConflictsWithInternalState(value)) 
      throw new ArgumentException("value"); 
     _prop = value; 
     NotifyPeriperalOfPropChange(_prop); 
     FirePropChangedEvent(/* whatever args might be needed */); 
    } 
} 

하지만, 그게 내가 그들을 재사용하게 해준다. 이제는 개인 필드 _prop을 만져도 자신감을 가질 수 있습니다. 왜냐하면 필자는 범위를 유지하고 주변 장치에 알리고 이벤트를 시작하기위한 인프라가 동일하기 때문입니다. 사람들은 내가 재산의 정신에서 일하고 있어요 그래서 속성을 구축하는 데 사용 나는이 같은 도구를 사용하고

_prop = CalculateSomeValue(); 

if (_prop < kPropMin) 
    _prop = kPropMin; 
else if (_prop > kPropMax * 2) 
    _prop = kPropMax; 

_prop /= 2; 

NotifyPeripheralOfPropChange(); 
FirePropChangedEvent(); 

:

이 날이 코드를 작성할 수 있습니다. 올바른 범위를 유지합니다 (그러나 던지지 마세요 - 저는 더 잘 알고 있습니다, 저는 구현 자입니다). 주변 장치와 화재 이벤트를 쳤고, 그것을 신중하고, 읽기 쉽고, 효율적으로 - 무차별 적으로하지 않습니다.

+0

+1이 글을 읽은 후에 이것은 아마도 내 동료의 생각 과정이라고 생각합니다. 그러나 논쟁의 여지가있는 코드의 목적을 위해 어떤 이유로 든 수업 외부에서 속성을 절대로 변경해서는 안됩니다. –

+0

질문 : 실용적인 접근법에서 '속성의 정신에 복종한다'고 말할 때, 속성이 클래스 외부에서 변경되지 않아야한다면 위에서 수행 한 것처럼 필드를 사용하여 업데이트해야한다는 것을 의미합니까? –

관련 문제