2012-01-19 3 views
2

this과 같은 다른 스레드를 읽었지만 제대로 작동하지 않았습니다. 지금 ClassB가의 새로운 객체를 생성하면 내가 상속 된 멤버를 숨기기위한 상속

_shouldBeInteger, _shouldBeBool, _shouldBeDateTime; 
shouldBeInteger,shouldBeBool,shouldBeDateTime 

을 얻을하지만 사용자에 _variables을 숨길

public class ClassA 
{ 
    public string _shouldBeInteger; 
    public string _shouldBeBool; 
    public string _shouldBeDateTime; 
} 

public class ClassB : ClassA 
{ 
    public int? shouldBeInteger 
    { 
     get { return (_shouldBeInteger != null) ? Convert.ToInt32(Convert.ToDouble(_shouldBeInteger)) : new int?(); } 
     set { _shouldBeInteger = Convert.ToString(value); } 
    } 

    //... same thing with datetime etc. 


} 

:

나는 두 개의 클래스를 얻었다. ClassB에서 비공개로 설정하면 무시되지만 문자열 값을 파싱하려면 해당 클래스에 액세스해야합니다.

업데이트

주로 그들이 쓰기 가능해야하는 이유입니다 ClassC 충전 ClassAs '값이 있습니다. 이 날의 작동 방식을 변경할 수있는 방법은 없지만를 ClassA의 프로그래머가 이상한에서 생산 때문에,를 ClassA의 제어 및 ClassB가

ClassC //not changeAble for me 
{ 
//infomagic filling values of ClassA  
} 

작동하지 않습니다 개인에를 ClassA 변수 설정에 완벽 해요 방법.

솔루션

를 ClassA는 쓸 수 있지만, inheritated보다 다른 클래스 읽을 수 없습니다 할 필요가 있기 때문에, 나는 마침내이있어 :

ClassB가이 포기하지 않고, theese 특성 작동됩니다
ClassA 
{ 
    public string _shouldBeInteger { protected get; set; } 
    //and so on 
} 

그들 밖에. 인텔리은 여전히 ​​표시되지만 사용을 고려할 수 있습니다

[EditorBrowsable(EditorBrowsableState.Never)] 

가를 해결하기 위해.

감사합니다.

+0

필드를 비공개로 설정하면 작동하지 않는다고 공개되었거나 보호 된 상태로 작동해야합니까? –

+0

언더 스코어 접두사는'public members'가 아닌'private members'의 표준입니다. – gdoron

+0

@ gdoron의 주석을 간과하기 만하면 밑줄 접두사는 CLS와 호환되지 않으므로 표준이 아니지만 CLS 준수에는 관심이 없습니다. 따라서 CLS 준수 경고는 최종 공개를 위해 좋은 상태가 아님을 나타냅니다. –

답변

8

난 당신이 사용하여 문제를 해결할 수 있다고 생각 :

public class ClassA 
{ 
    protected string _shouldBeInteger; 
    protected string _shouldBeBool; 
    protected string _shouldBeDateTime; 
} 

그래서 그 변수는 파생 클래스에 액세스 할 수 있지만 사용자에 있습니다.

는 사용자 업데이트 후 편집 : 나는이 당신을 위해 VALI의 해결책이 될 수 있는지 알아,하지만 노력하지 않는
: 당신이 생각하는 것처럼

public class ClassB : ClassA 
{ 
    public new int? _shouldBeInteger 
    { 
     get { return (base._shouldBeInteger != null) ? 
        Convert.ToInt32(Convert.ToDouble(base._shouldBeInteger)) : 
        new int?(); } 
     set { base._shouldBeInteger = Convert.ToString(value); } 
    } 
} 
+0

누군가 왜 downvote를 설명 할 수 있습니까? 내 대답에 무슨 문제가 있니? – Marco

+0

+1 아마도 필드 이름을 제외하고는 해당 필드 이름을 보호하는 것이 유효한 해결책 일 수 있습니다. 그들이 공개 될 필요가 있지 않는 한 OP는 그것을 말하지 않았다. –

+0

나는 ClassA에 대한 통제권이 없다는 인상을 받았다. 그게 아니라면 내가 취소하지 않을거야 :) – MattDavey

4

상속 구성원을 숨길 수 없습니다. new 수정자는 기본 멤버를 "숨기"위해 존재하지만 기본 유형과 대화 할 때 좋지 않습니다.

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

당신은 필드의 액세스 수준 (선호하는 방법)을 변경할 수 있습니다 또는 당신이 대신 상속의 클래스를 포장하고 포장 클래스에 위임하는 간단한 통과 방법을 제공 할 수 있습니다.이것은 Adapter Pattern라고 : 그냥 옆으로

public class ClassB 
{ 
    private ClassA _wrappedClass; 
} 

을 공개 필드는 일반적으로 민간 분야에 사용되는 이름 지정 규칙을 따르고 있습니다.

파생 클래스에 필요한 액세스 수준은 protected입니다. 회원이 공개적으로 사용되었지만 동일한 어셈블리에서 사용되는 경우 protected internal을 사용할 수 있습니다. 멤버가 다른 어셈블리에서 공개적으로 사용되는 경우 리팩토링을 제안합니다. 당신이를 ClassA을 제어 할 수없는 경우

+0

좋은 지적, upvoted! – Marco

+1

OP 업데이트를 보았습니다. 내 대답을 편집했습니다. 어떻게 생각하십니까? 탈출구가 될 수 있을까요? – Marco

+0

수업을 마무리하고 있습니다. 물론 가능합니다. 지금 다른 길을 찾았지만 다음 번엔 그 일찍 생각할 것입니다. 감사. – Harry

0

, 당신과 같이 래퍼/어댑터 클래스를 만들어야합니다 :

public class ClassB 
{ 
    private readonly _classA = new ClassA(); 

    public int? shouldBeInteger 
    { 
     get 
     { 
      return (this._classA._shouldBeInteger != null) 
       ? Convert.ToInt32(Convert.ToDouble(this._classA._shouldBeInteger)) 
       : new int?(); 
     } 
     set 
     { 
      this._classA._shouldBeInteger = Convert.ToString(value); 
     } 
    } 
} 
+1

내부 클래스 이름에'ClassA'를 사용하지 마십시오 ... private classA = new ClassA() ;; – Marco

+0

@Marco 당신 말이 맞아요. 원래는 사유지 였지만, 마지막 순간의 필드 :) – MattDavey

1

문제는 당신이 기본 클래스의 공공 필드를 선언한다는 것입니다. 상속의 다형성을 위반하지 않기 위해 기본 클래스의 모든 공용 클래스가 모든 파생 클래스에도 공개되어야합니다. 이를 변경할 수 있다면 ClassB가 ClassA를 기대하는 것으로 전달 될 수 있다는 것을 확신 할 수 없습니다.

다른 사람들이 제안했듯이, 파생 클래스가 볼 수있는 것을 제외하고는 기본 클래스 필드가 보호 대상으로 선언되기를 원할 것입니다.

그러나 ClassA의 실제 인스턴스를 통해 액세스해야하는 경우 해당 클래스를 비공개로 선언하고 파생 클래스가 재정의 할 수있는 가상 공개 속성을 제공 할 수 있습니다. 적어도 파생 클래스가 동작을 변경할 수는 있지만 실제로 숨길 수는 없습니다.

또한 맞지 않는 경우 대체 원칙이 실제로 진행되고 있기 때문에 상속 대신 구성을 사용하는 것이 좋습니다. 이는 상속의 기본입니다. 이 경우 모두에서

0
public class ClassB 
{ 
    private int shouldBeInteger; 

    public int ShouldBeInteger 
    { 
     get { return shouldBeInteger; } 
     set { shouldBeInteger = value; } 
    } 

} 

또는

public class ClassB 
    { 

    public int ShouldBeInteger{ get; set; } 

    } 

는 ShouldBeInteger는 클래스 외부 액세스가가 능.

은 첫 번째 경우 클래스 외부 accesible 수 없습니다 민간 분야, 민간 신청에

값이 공공 필드를 통해 설정 될 수 있었다.

번째 경우에, 컴파일러는 전용 백킹 필드를 생성하고 상기와 동일한

과정을 수행. 이것은 자동 구현 된 속성입니다.

희망이 도움이 될 수 있습니다.