C#할 수 있는 공개적으로 상속 방법 수 숨겨진(예:어 프라이빗 파생 등)

StackOverflow https://stackoverflow.com/questions/106383

  •  01-07-2019
  •  | 
  •  

문제

한 두 가지가 아닌 공공 무 공용 방법을 A 와 B,그리고 내가 만들 derivedclass 는 상속을 통해.

예:

public DerivedClass : BaseClass {}

지금 내가 원하는 방법을 개발 C derivedclass 는 사용하는 A and B.는 방법이 있 나는 무시할 수 있습 방법을 A 와 B 개인에 derivedclass 는도록 유일한 방법 C 에 노출된 사람을 사용하고자하는 내 derivedclass 는?

도움이 되었습니까?

해결책

그것은 가능하지 않은 이유는?

C#,그것은 강요할 경우 상속 방법을 공개해야 합니다 그들을 공개한다.그렇지 않으면 그들은 기대하지 않기에서 파생되는 클래스에서는 첫 번째 장소입니다.

를 사용하는 대신 이의 관계,사용할 수 있는 관계이다.

언어 디자이너들이 허용하지 않는 목적에 사용할 수 있도록 상속세요.

예를 들어 하나는 실수를 혼동하는 클래스 자동차 클래스에서 파생되는 엔진을 얻을 그것의 기능이 있습니다.하지만 엔진 기능을 사용하는 자동차.그래서 당신이 원하는 것을 사용하는 관계이다.차량의 사용자가 원하지 않 액세스 인터페이스의 엔진입니다.그리고 자동차 자체를 혼동해서는 안 엔진의 방법으로 될 것이라고 확신합니다.나 자동차의 미래를 유도.

그래서 그들은 그것을 허용하지 않기에서 당신을 보호하기 위해 나쁜 상속 계층 구조입니다.

어떻게 해야 할까요?

대신 구현해야 합니다 인터페이스가 있습니다.이것을 무료 있는 기능을 사용하여는 관계이다.

다른 언어:

C++에서 당신은 단순히 지정할 수정하기 전에 기본 클래스의 개인,공공 또는 보호됩니다.이것은 모든 멤버들의베이스는 공개하는 지정된 액세스 수준이다.어리석게 보이게는 할 수 없에서 같은 C#.

재구성된 코드:

interface I
{
    void C();
}

class BaseClass
{
    public void A() { MessageBox.Show("A"); }
    public void B() { MessageBox.Show("B"); }
}

class Derived : I
{
    public void C()
    {
        b.A();
        b.B();
    }

    private BaseClass b;
}

내가 이해의 이름은 위의 클래스는 약간의 논쟁:)

다른 제안 사항:

다른 사람을 만들기 위해 제안 A()B()공과 던지 예외가 있습니다.그러나 이것이 만들지 않는 친절 등에 대한 사람들이 사용하지 않습니다.

다른 팁

할 때,예를 들어,상속에서 List<object>,그리고 숨기려면 직접 Add(object _ob) 회원:

// the only way to hide
[Obsolete("This is not supported in this class.", true)]
public new void Add(object _ob)
{
    throw NotImplementedException("Don't use!!");
}

그것이 정말로 가장 바람직한 솔루션이지만,그것은 작업을 수행합니다.Intellisense 도 받지만,컴파일 시간에 당신을 얻는다:

오류 CS0619:'TestConsole.TestClass.추가(TestConsole.TestObject)'에 사용되지 않:'이에서 지원되지 않습니다.'

처럼 들리는 나쁜 생각이 아니다. Liskov 지 않을 것입니다.

당신이 원하지 않는 경우는 소비자의 derivedclass 는 액세스할 수 있는 방법을 DeriveClass.A()및 derivedclass 는.(B)는 것이 좋습니다 것입니다 derivedclass 는 구현해야 중 일부 공용 인터페이스 IWhateverMethodCIsAbout 및 소비자의 derivedclass 는 실제로 이야기를 IWhateverMethodCIsAbout 과 아무것도 알고 구현에 대해 공공 무 또는 derivedclass 는 모든.

당신이 필요로 구성하지 상속입니다.

class Plane
{
  public Fly() { .. }
  public string GetPilot() {...}
}

이제 필요한 경우 특별한 종류의 비행기와 같이 하나 있는 PairOfWings=2 지만 그렇지 않으면 모든 것이 비행기를 할 수 있습니다..당신이 상속기입니다.여 이를 선언하는 파생을 충족 계약의 기본 클래스고 대체할 수 있습 깜박하지 않고 어디든지 기본 클래스가 예상된다.예:LogFlight(비행기로)작업을 계속으로 복 인스턴스입니다.

그러나만 필요한 경우에는 즉시 행동에 대해 새로운 새를 만들고 있지 않은 기꺼이 지원하는 완벽한 기본 클래스 계약을 구성하는 대신.이 경우,리팩터 동작하는 방법의 재사용으로 새로운 유형입니다.지금 만들고에 대한 참조를 이 클래스는 모두에서 비행기와 조류입니다.을 상속하지 않기 때문에 새을 지원하지 않는 완벽한 기본 클래스 계약...(예:를 제공할 수 없 GetPilot()).

같은 이유로, 을 줄일 수 없습니다 가시성 의 기본 클래스 메소드를 대체할 경우.. 무시할 수 있습과 기본 개인 방법을 공중에서 유래하지만 그 반대의 경우도 마찬가지입니다.예:이 예제에서는 경우,파생의 모형 비행기"BadPlane"그리고 무시하고"숨"GetPilot()-그것은 개인;클라이언트 방법 LogFlight(비행기 p)이 작업에 대한 가장 비행기만이"에 대한 BadPlane"구현 하는 경우의 LogFlight 발생을 필요로/전화 GetPilot(). 때문에 모든 파생어의 기본 클래스가 될 것으로 예상된'치환'어디든지 기본 클래스의 param,예상되는이 허용되지 않습니다.

은 작업을 수행할 수 있는 유일한 방법이 나가 알을 사용하는 것은 관계와 구현하려는 기능을 노출한다.

@브라이언 R.봉디 나를 지적하는 흥미로운 기사에 숨어있는 상속을 통해와 키워드입니다.

http://msdn.microsoft.com/en-us/library/aa691135(VS.71).aspx

그래서 해결 방법으로 난 것이 좋:

class BaseClass
{
    public void A()
    {
        Console.WriteLine("BaseClass.A");
    }

    public void B()
    {
        Console.WriteLine("BaseClass.B");
    }
}

class DerivedClass : BaseClass
{
    new public void A()
    {
        throw new NotSupportedException();
    }

    new public void B()
    {
        throw new NotSupportedException();
    }

    public void C()
    {
        base.A();
        base.B();
    }
}

이 방법은 이와 같은 코드를 던져 코드 액세스 보안을 통해 보호:

    DerivedClass d = new DerivedClass();
    d.A();

숨어있는 매우 미끄러운 슬로프 등이 있습니다.주요 주제,IMO,다음과 같습니다:

  • 이에 따라 디자인-time 선언이 유형의 인스턴스 미 당신이 뭔가를 할 경우 다음과 같 공공 무 obj=새로운 서브 클래스(),다음 전화 obj.A(),숨기는 것은 패배한다.공공 무.A()실행됩니다.

  • 숨기기 할 수 있는 아주 쉽게호 동작(또는 행동의 변경)에 기본 형식입니다.이것은 분명히 의 더 적은 관심을 때 당신의 자신의 모 양쪽의 방정식,또는 전화하는 경우'기초입니다.xxx'의 일부입의 하위 회원입니다.

  • 는 경우에 당신은 실제로 자신의 양쪽의 기지/서브 클래스 방정식,다음을 고안 수 있어야 더 관리 솔루션을 제도화 숨기/숨기.

내가 말할 것이 있는 경우에는 코드는 원하는 이와 함께,그것은 최적의 설계 코드 베이스.그것은 일반적으로 등록하십시오 클래스의 한 수준에서의 계층 구조 필요로 하는 특정 공 서명하는 동안 또 다른 클래스에서 파생되는 클래스가 필요하지 않습니다.

다가오는 코딩 패러다임"라는 구성을 통해 상속입니다." 이것이 바로 떨어져의 원리의 객체지향 개발(특히 단 책임의 원칙과 개방/폐쇄 원칙).

불행하게도,이 방법은 우리가 많이 개발자가 배운 객체지향 개념,우리가 형성된 습관을 바로에 대해 생각하고 상속의 대신 구성.우리는 우리가 더 큰 가지는 클래스들은 많은 서로 다른 책임은 단순히 있을 수도 있기 때문에 포함 같이"현실 세계"개체입니다.이어질 수 있는 클래스 계층 구조는 5+은 깊은 수준입니다.

불행한 부작용하는 개발자는 일반적으로 생각하지 않는 경우에 대해 다루는 상속되는 상속 중 하나를 형성하는 강력한 형태의 종속성할 수 있는 적로 소개합니다.파생된 클래스는 지금 강하게 의존에서 클래스를 상속되었습니다.이 코드를 더욱 부서지기 쉬운 장기 지도 혼란이 문제가 변화하는 특정한 행동을 기본 클래스에서 휴식 파생된 클래스에서는 모호한다.

방법 중 하나는 휴식의 코드는 인터페이스를 통해 다음과 같이 언급에서 또 다른 대답이다.이것은 똑똑한 것은 어쨌든 당신이 원하는 클래스의 외부 종속성을 바인딩을 추상화,지 않은 콘크리트/파생된 형식입니다.이것을 변경할 수 있도록 구현을 변경하지 않고 인터페이스는 모든 영향을 미치지 않으면서 코드의 라인에 의존 클래스입니다.

전 오히려 이상 유지 시스템으로 수백/수천에/더 많은 클래스를 모든 작고 느슨하게 결합된 것보다,처리하는 시스템을 많이 사용하는 다형성/속가 적은 클래스는 더 단단히 결합되어 있다.

리소스 밖에서 객체지향 개발은 로버트 C.마틴의 책, 민첩한 소프트웨어 개발,원리,패턴 및 관행.

면 그들은 정의된 대중에서 원래의 클래스를 재정의할 수 없습니다 그 개인에서 파생된 클래스입니다.그러나,당신은 만들 수 있는 공공 방법을 던지는 제외하고 구현하 자신의 개인 기능입니다.

편집:Jorge 페레이라이 올바른 것입니다.

는 질문에 대답이"아니",하나의 끝을 내가 지적하고자하는 다른 사람을 위해 여기에 도착하는(주는 영업 이익 종류의 암시하는 어셈블리에 액세스를 제 3 자에 의해).할 때 다른 사람을 참조 어셈블리,Visual Studio 해야를 기리는 다음과 같은 특성을 포함합니다 그래서에 표시되지 않습니다 intellisense(숨김하지만,여전히 수 있습 라는,그래서 조심):

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]

는 경우에 당신은 다른 선택의 여지가 없었다,당신은 당신을 사용할 수 있어야 new 에서 방법을 숨기는 기본 형식 방법,반환 => throw new NotSupportedException();, 며,결합하는 특성이다.

다른 속임수에 따라 달라지 않을 상속하는 기본 클래스에서 가능하면 어디로 기본에는 해당하는 인터페이스(등 IList<T>List<T>).인터페이스를 구현하"명시적으로"도 숨기기 사람들에서 방법을 intellisense 클래스에는 유형입니다.예를 들어:

public class GoodForNothing: IDisposable
{
    void IDisposable.Dispose() { ... }
}

의 경우에는 var obj = new GoodForNothing(), 이, Dispose() 는 방법에서 사용할 수 없 obj.그러나,그것은 누구나 사용할 수 있는 명시적으로 입력 캐스트 obj 하기 IDisposable.

또한,당신은 또한 포장 기본 유형을 대신 상속에 숨기는 몇 가지 방법:

public class MyList<T> : IList<T>
{
    List<T> _Items = new List<T>();
    public T this[int index] => _Items[index];
    public int Count => _Items.Count;
    public void Add(T item) => _Items.Add(item);
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    void ICollection<T>.Clear() => throw new InvalidOperationException("No you may not!"); // (hidden)
    /*...etc...*/
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top