Programing

왜 정적 클래스를 상속받을 수 없습니까?

lottogame 2020. 4. 29. 08:03
반응형

왜 정적 클래스를 상속받을 수 없습니까?


실제로 어떤 상태가 필요하지 않은 여러 클래스가 있습니다. 조직의 관점에서, 나는 그것들을 계층 구조에 넣고 싶습니다.

그러나 정적 클래스에 대한 상속을 선언 할 수없는 것 같습니다.

그런 것 :

public static class Base
{
}

public static class Inherited : Base
{
}

작동 안 할 것이다.

왜 언어 디자이너들이 그런 가능성을 닫았습니까?


여기 에서 인용 :

이것은 실제로 의도적으로 설계된 것입니다. 정적 클래스를 상속받을 이유가없는 것 같습니다. 클래스 이름 자체를 통해 항상 액세스 할 수있는 공개 정적 멤버가 있습니다. 정적 인 물건을 상속받는 것으로 본 유일한 이유는 입력하는 두 문자를 저장하는 것과 같은 나쁜 이유였습니다.

정적 멤버를 직접 범위로 가져 오는 메커니즘을 고려해야하는 이유가있을 수 있지만 (Orcas 제품주기 이후에이를 실제로 고려할 것임) 정적 클래스 상속은가는 방법이 아닙니다. 사용하는 잘못된 메커니즘이며 작동합니다. 정적 클래스에있는 정적 멤버에만 해당됩니다.

(Mads Torgersen, C # Language PM)

channel9의 다른 의견

.NET의 상속은 인스턴스 기반에서만 작동합니다. 정적 메소드는 인스턴스 레벨이 아닌 유형 레벨에서 정의됩니다. 정적 메서드 / 속성 / 이벤트에서는 재정의가 작동하지 않는 이유입니다 ...

정적 메소드는 메모리에서 한 번만 보유됩니다. 작성된 가상 테이블 등이 없습니다.

.NET에서 인스턴스 메소드를 호출하면 항상 현재 인스턴스를 제공합니다. 이것은 .NET 런타임에 숨겨져 있지만 발생합니다. 각 인스턴스 메소드에는 첫 번째 인수로 메소드가 실행되는 오브젝트에 대한 포인터 (참조)가 있습니다. 정적 메서드에서는 발생하지 않습니다 (유형 수준에서 정의되었으므로). 컴파일러는 호출 할 메소드를 어떻게 선택해야합니까?

(littleguru)

그리고 귀중한 아이디어로서 littleguru 는이 문제에 대한 부분적인 "해결책": Singleton 패턴을 가지고 있습니다.


정적 클래스를 상속 할 수없는 주된 이유는 클래스가 추상적이고 봉인되어 있기 때문입니다 (이로 인해 해당 클래스의 인스턴스가 생성되지 않음).

그래서 이건:

static class Foo { }

이 IL로 컴파일합니다.

.class private abstract auto ansi sealed beforefieldinit Foo
  extends [mscorlib]System.Object
 {
 }

이런 식으로 생각하십시오 : 다음과 같이 유형 이름을 통해 정적 멤버에 액세스하십시오.

MyStaticType.MyStaticMember();

해당 클래스에서 상속받은 경우 새 유형 이름을 통해 클래스에 액세스해야합니다.

MyNewType.MyStaticMember();

따라서 새 항목은 코드에서 사용될 때 원본과 관계가 없습니다. 다형성과 같은 것들에 대한 상속 관계를 이용할 수있는 방법은 없습니다.

아마도 당신은 원래 수업에서 일부 항목을 확장하고 싶다고 생각하고 있습니다. 이 경우 원본의 멤버를 완전히 새로운 유형으로 사용하는 것을 막을 수있는 것은 없습니다.

기존 정적 유형에 메소드를 추가하려고 할 수 있습니다. 확장 방법을 통해 이미 그렇게 할 수 있습니다.

아마도 Type런타임에 함수에 정적을 전달 하고 메서드의 기능을 정확히 몰라도 해당 유형의 메서드를 호출 하려고 할 수 있습니다 . 이 경우 인터페이스를 사용할 수 있습니다.

따라서 결국 정적 클래스 상속을 통해 아무것도 얻지 못합니다.


클래스 계층 구조를 사용하여 달성하려는 것은 단순히 네임 스페이스를 통해 달성 할 수 있습니다. 따라서 C #과 같은 네임 스페이스를 지원하는 언어는 정적 클래스의 클래스 계층 구조를 구현할 필요가 없습니다. 클래스를 인스턴스화 할 수 없으므로 네임 스페이스를 사용하여 얻을 수있는 클래스 정의의 계층 구조 만 있으면됩니다.


대신 컴포지션을 사용할 수 있습니다. 그러면 정적 유형에서 클래스 객체에 액세스 할 수 있습니다. 그러나 여전히 인터페이스 또는 추상 클래스를 구현할 수 없습니다


상속 된 클래스 이름을 통해 "상속 된"정적 멤버에 액세스 할 수 있지만 정적 멤버는 실제로 상속되지는 않습니다. 이것이 부분적으로 가상이거나 추상적 일 수없고 재정의 될 수없는 이유입니다. 예제에서 Base.Method ()를 선언 한 경우 컴파일러는 Inherited.Method ()에 대한 호출을 Base.Method ()에 다시 매핑합니다. Base.Method ()를 명시 적으로 호출 할 수도 있습니다. 작은 테스트를 작성하고 리플렉터로 결과를 볼 수 있습니다.

정적 멤버를 상속 할 수없고 정적 클래스에 정적 멤버 포함 할 수 있다면 정적 클래스를 상속하면 어떤 이점이 있습니까?


흠 ... 정적 메소드로 채워진 비 정적 클래스가 있다면 훨씬 다를 것입니다 ..?


A workaround you can do is not use static classes but hide the constructor so the classes static members are the only thing accessible outside the class. The result is an inheritable "static" class essentially:

public class TestClass<T>
{
    protected TestClass()
    { }

    public static T Add(T x, T y)
    {
        return (dynamic)x + (dynamic)y;
    }
}

public class TestClass : TestClass<double>
{
    // Inherited classes will also need to have protected constructors to prevent people from creating instances of them.
    protected TestClass()
    { }
}

TestClass.Add(3.0, 4.0)
TestClass<int>.Add(3, 4)

// Creating a class instance is not allowed because the constructors are inaccessible.
// new TestClass();
// new TestClass<int>();

Unfortunately because of the "by-design" language limitation we can't do:

public static class TestClass<T>
{
    public static T Add(T x, T y)
    {
        return (dynamic)x + (dynamic)y;
    }
}

public static class TestClass : TestClass<double>
{
}

You can do something that will look like static inheritance.

Here is the trick:

public abstract class StaticBase<TSuccessor>
    where TSuccessor : StaticBase<TSuccessor>, new()
{
    protected static readonly TSuccessor Instance = new TSuccessor();
}

Then you can do this:

public class Base : StaticBase<Base>
{
    public Base()
    {
    }

    public void MethodA()
    {
    }
}

public class Inherited : Base
{
    private Inherited()
    {
    }

    public new static void MethodA()
    {
        Instance.MethodA();
    }
}

The Inherited class is not static itself, but we don't allow to create it. It actually has inherited static constructor which builds Base, and all properties and methods of Base available as static. Now the only thing left to do make static wrappers for each method and property you need to expose to your static context.

There are downsides like the need for manual creation of static wrapper methods and new keyword. But this approach helps support something that is really similar to static inheritance.

P.S. We used this for creating compiled queries, and this actually can be replaced with ConcurrentDictionary, but a static read-only field with its thread safety was good enough.


My answer: poor design choice. ;-)

This is an interesting debate focused on syntax impact. The core of the argument, in my view, is that a design decision led to sealed static classes. A focus on transparency of the static class's names appearing at the top level instead of hiding ('confusing') behind child names? One can image a language implementation that could access the base or the child directly, confusing.

A pseudo example, assuming static inheritance was defined in some way.

public static class MyStaticBase
{
    SomeType AttributeBase;
}

public static class MyStaticChild : MyStaticBase
{
    SomeType AttributeChild;
}

would lead to:

 // ...
 DoSomethingTo(MyStaticBase.AttributeBase);
// ...

which could (would?) impact the same storage as

// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...

Very confusing!

But wait! How would the compiler deal with MyStaticBase and MyStaticChild having the same signature defined in both? If the child overrides than my above example would NOT change the same storage, maybe? This leads to even more confusion.

I believe there is a strong informational space justification for limited static inheritance. More on the limits shortly. This pseudocode shows the value:

public static class MyStaticBase<T>
{
   public static T Payload;
   public static void Load(StorageSpecs);
   public static void Save(StorageSpecs);
   public static SomeType AttributeBase
   public static SomeType MethodBase(){/*...*/};
}

Then you get:

public static class MyStaticChild : MyStaticBase<MyChildPlayloadType>
{
   public static SomeType AttributeChild;
   public static SomeType SomeChildMethod(){/*...*/};
   // No need to create the PlayLoad, Load(), and Save().
   // You, 'should' be prevented from creating them, more on this in a sec...
} 

Usage looks like:

// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...

The person creating the static child does not need to think about the serialization process as long as they understand any limitations that might be placed on the platform's or environment's serialization engine.

Statics (singletons and other forms of 'globals') often come up around configuration storage. Static inheritance would allow this sort of responsibility allocation to be cleanly represented in the syntax to match a hierarchy of configurations. Though, as I showed, there is plenty of potential for massive ambiguity if basic static inheritance concepts are implemented.

I believe the right design choice would be to allow static inheritance with specific limitations:

  1. No override of anything. The child cannot replace the base attributes, fields, or methods,... Overloading should be ok, as long as there is a difference in signature allowing the compiler to sort out child vs base.
  2. Only allow generic static bases, you cannot inherit from a non-generic static base.

You could still change the same store via a generic reference MyStaticBase<ChildPayload>.SomeBaseField. But you would be discouraged since the generic type would have to be specified. While the child reference would be cleaner: MyStaticChild.SomeBaseField.

I am not a compiler writer so I am not sure if I am missing something about the difficulties of implementing these limitations in a compiler. That said, I am a strong believer that there is an informational space need for limited static inheritance and the basic answer is that you can't because of a poor (or over simple) design choice.


Static classes and class members are used to create data and functions that can be accessed without creating an instance of the class. Static class members can be used to separate data and behavior that is independent of any object identity: the data and functions do not change regardless of what happens to the object. Static classes can be used when there is no data or behavior in the class that depends on object identity.

A class can be declared static, which indicates that it contains only static members. It is not possible to use the new keyword to create instances of a static class. Static classes are loaded automatically by the .NET Framework common language runtime (CLR) when the program or namespace that contains the class is loaded.

Use a static class to contain methods that are not associated with a particular object. For example, it is a common requirement to create a set of methods that do not act on instance data and are not associated to a specific object in your code. You could use a static class to hold those methods.

Following are the main features of a static class:

  1. They only contain static members.

  2. They cannot be instantiated.

  3. They are sealed.

  4. They cannot contain Instance Constructors (C# Programming Guide).

Creating a static class is therefore basically the same as creating a class that contains only static members and a private constructor. A private constructor prevents the class from being instantiated.

The advantage of using a static class is that the compiler can check to make sure that no instance members are accidentally added. The compiler will guarantee that instances of this class cannot be created.

Static classes are sealed and therefore cannot be inherited. They cannot inherit from any class except Object. Static classes cannot contain an instance constructor; however, they can have a static constructor. For more information, see Static Constructors (C# Programming Guide).


When we create a static class that contains only the static members and a private constructor.The only reason is that the static constructor prevent the class from being instantiated for that we can not inherit a static class .The only way to access the member of the static class by using the class name itself.Try to inherit a static class is not a good idea.

참고URL : https://stackoverflow.com/questions/774181/why-cant-i-inherit-static-classes

반응형