programing

상속된 구성원 숨기기

magicmemo 2023. 5. 1. 20:49
반응형

상속된 구성원 숨기기

상속받은 멤버들을 효과적으로 숨길 방법을 찾고 있습니다.저는 공통 기본 클래스에서 상속되는 클래스 라이브러리를 가지고 있습니다.최신 하위 클래스 중 일부는 종속성 속성을 상속합니다. 종속성 속성은 오래되어 IntelliSense를 사용하거나 비주얼 디자이너에서 클래스를 사용할 때 약간 혼란스러울 수 있습니다.

이러한 클래스는 모두 WPF 또는 Silverlight 2.0용으로 컴파일되도록 작성된 컨트롤입니다.에 대해 알고 있습니다.ICustomTypeDescriptor그리고.ICustomPropertyProvider하지만 실버라이트에서는 사용할 수 없을 거라 확신합니다.

기능적인 문제라기보다는 사용성 문제입니다.어떻게 해야 하나?

갱신하다

가 정말 중 는 제 로부터 온 제가에, ▁the▁▁with▁i▁some▁member▁thatties▁tool▁proper▁for▁come▁i▁because▁ancestors'▁from없수▁specific숨▁oft▁of▁do▁a▁can멤제니가▁own▁the습▁my▁like다길를버▁hide▁and,▁are▁i▁really▁to▁not저는'▁would▁designingmnew교환입니다.(알아요, 말도 안 돼요)

위의 Michael이 제안하는 것처럼 재정의하고 사람들이 재정의된(sp?) 메서드를 사용하지 못하도록 하려면 해당 메서드를 사용하지 않는 것으로 표시합니다.

[Obsolete("These are not supported in this class.", true)]
public override  void dontcallmeanymore()
{
}

두 번째 parm이 true로 설정된 경우, 누군가가 해당 메서드를 호출하려고 하면 컴파일러 오류가 생성되고 첫 번째 parm의 문자열이 메시지가 됩니다.parm2가 false이면 컴파일러 경고만 생성됩니다.

내가 알기로는 상속된 구성원의 사용을 방지할 수 없지만 EditorBrowsableAttribute를 사용하여 IntelliSense에서 해당 구성원을 숨길 수 있습니다.

Using System.ComponentModel;

[EditorBrowsable(EditorBrowsableState.Never)]
private string MyHiddenString = "Muahahahahahahahaha";

편집: 문서 주석에서 이것을 보았는데, 이것은 이 목적에 약간 쓸모가 없게 만듭니다.

이 특성이 "같은 어셈블리의 클래스에서 구성원을 억제하지 않음"을 나타내는 중요한 참고 사항이 있습니다.그것은 사실이지만 완전하지는 않습니다.실제로 속성은 동일한 솔루션의 클래스에서 구성원을 억제하지 않습니다.

가능한 한 가지 방법은 다른 클래스에서 확장하는 것이 아니라 개체를 포함하는 것입니다.이렇게 하면 노출할 대상을 노출하는 데 있어 가장 유연한 방법이 제공되지만, 해당 유형의 개체가 꼭 필요한 경우에는 이상적인 솔루션이 아닙니다(그러나 개체를 처음부터 노출할 수도 있음).

따라서:

public class MyClass : BaseClass
{
    // Your stuff here
}

다음이 됩니다.

public class MyClass
{
    private BaseClass baseClass;

    public void ExposeThisMethod()
    {
        baseClass.ExposeThisMethod();
    }
}

또는:

public class MyClass
{
    private BaseClass baseClass;

    public BaseClass BaseClass
    {
        get
        {
            return baseClass;
        }
    }
}

저는 당신이 가장 최소한의 해킹 방법은 상속이 아닌 구성을 고려하는 것이라고 생각합니다.

또는 원하는 구성원이 있는 인터페이스를 만들고, 파생된 클래스가 해당 인터페이스를 구현하고, 인터페이스를 기반으로 프로그래밍할 수 있습니다.

이것에 지금은 꽤 , 위한 가장 방법은 을 이에대몇한있알며,현오었지만되를,위가간다같선다것니입으로 입니다.new private.

제가 현재 연구하고 있는 예를 생각해 보십시오. 여기에는 타사 DLL의 모든 방법을 사용할 수 있는 API가 있습니다.나는 그들의 방법을 취해야 하지만, 나는 a를 사용하고 싶습니다."getThisValue" 및 "setThisValue" 메서드 대신 Net 속성을 사용합니다.그래서 저는 두 번째 클래스를 만들고 첫 번째 클래스를 상속하고 get 및 set 메서드를 사용하는 속성을 만든 다음 원래 get 및 set 메서드를 비공개로 재정의합니다.그것들은 여전히 그것들 위에 뭔가 다른 것을 만들고자 하는 사람들이 이용할 수 있습니다. 하지만 그들이 단지 제가 만들고 있는 엔진을 사용하기를 원한다면, 그들은 방법 대신에 속성을 사용할 수 있을 것입니다.

이중 클래스 방법을 사용하면 사용할 수 없는 것에 대한 제한이 없어집니다.new회원들을 숨기겠다는 선언사용할 수 없습니다.override구성원이 가상으로 표시된 경우.

public class APIClass
{
    private static const string DllName = "external.dll";

    [DllImport(DllName)]
    public extern unsafe uint external_setSomething(int x, uint y);

    [DllImport(DllName)]
    public extern unsafe uint external_getSomething(int x, uint* y);

    public enum valueEnum
    {
        On = 0x01000000;
        Off = 0x00000000;
        OnWithOptions = 0x01010000;
        OffWithOptions = 0x00010000;
    }
}

public class APIUsageClass : APIClass
{
    public int Identifier;
    private APIClass m_internalInstance = new APIClass();

    public valueEnum Something
    {
        get
        {
            unsafe
            {
                valueEnum y;
                fixed (valueEnum* yPtr = &y)
                {
                    m_internalInstance.external_getSomething(Identifier, yPtr);
                }
                return y;
            }
        }
        set
        {
            m_internalInstance.external_setSomething(Identifier, value);
        }
    }

    new private uint external_setSomething(int x, float y) { return 0; }
    new private unsafe uint external_getSomething(int x, float* y) { return 0; }
}

이제 valueEnum을 두 클래스 모두에서 사용할 수 있지만 APIUsageClass 클래스에는 속성만 표시됩니다.API 클래스는 기존 API를 확장하거나 다른 방식으로 사용하려는 사용자를 위해 계속 사용할 수 있으며 API Usage 클래스는 보다 단순한 것을 원하는 사용자를 위해 사용할 수 있습니다.

궁극적으로 제가 할 일은 APIC 클래스를 내부로 만들고 상속받은 클래스만 노출하는 것입니다.

대부분의 독자들이 기대하는 지능을 포함하여 완전히 숨기고 사용하지 않도록 표시하는 것.

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

저는 제안된 솔루션을 모두 테스트했고 그들은 실제로 새로운 멤버를 숨기지 않습니다.

하지만 이 방법은 다음과 같습니다.

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}

그러나 코드 뒤에서는 여전히 액세스할 수 있으므로 사용되지 않는 속성을 추가합니다.

[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}

위에서 C#에서는 상속받은 방법과 속성에 대한 접근 수식어를 변경할 수 없다고 분명히 언급했지만, 저는 암묵적인 캐스팅을 이용한 일종의 '가짜 상속'을 통해 이 문제를 극복했습니다.

예:

public class A
{
      int var1;
      int var2;

      public A(int var1, int var2)
      {
            this.var1 = var1;
            this.var2 = var2;
      }
      public void Method1(int i)
      {
            var1 = i;
      }
      public int Method2()
      {
            return var1+var2;
      }
}

이제 당신이 원하는 것은class B에서물은에서 class A 일부 하거나 Method1을 .

public class B
{
      private A parent;

      public B(int var1, int var2)
      {
            parent = new A(var1, var2);
      } 

      int var1 
      {
            get {return this.parent.var1;}
      }
      int var2 
      {
            get {return this.parent.var2;}
            set {this.parent.var2 = value;}
      }

      public Method1(int i)
      {
            this.parent.Method1(i*i);
      }
      private Method2()
      {
            this.parent.Method2();
      }


      public static implicit operator A(B b)
      {
            return b.parent;
      }
}

마지막에 암묵적인 캐스팅을 포함시킴으로써, 우리가 치료할 수 있게 해줍니다.B로서의 목적.A우리가 필요할 때.암시적 캐스트를 정의하는 것도 유용할 수 있습니다.A->B.

이 접근 방식의 가장 큰 결함은 "상속"하려는 모든 메서드/속성을 다시 작성해야 한다는 것입니다.이 접근법에는 아마도 더 많은 결함이 있겠지만, 저는 그것을 일종의 "가짜 상속"으로 사용하는 것을 좋아합니다.

참고:

이를 통해 액세스 가능성을 변경할 수 있습니다.public속성, 그것은 만드는 문제를 해결하지 못합니다.protected공공 재산

인터페이스를 사용할 수 있습니다.

    public static void Main()
    {
        NoRemoveList<string> testList = ListFactory<string>.NewList();

        testList.Add(" this is ok ");

        // not ok
        //testList.RemoveAt(0);
    }

    public interface NoRemoveList<T>
    {
        T this[int index] { get; }
        int Count { get; }
        void Add(T item);
    }

    public class ListFactory<T>
    {
        private class HiddenList: List<T>, NoRemoveList<T>
        {
            // no access outside
        }

        public static NoRemoveList<T> NewList()
        {
            return new HiddenList();
        }
    }

언급URL : https://stackoverflow.com/questions/1528/hiding-inherited-members

반응형