Почему я не могу наследовать статические классы?



У меня есть несколько классов, которые не нужны любому государству. С организационной точки зрения, я хотел бы поставить их в иерархии.



но, кажется, я не могу объявить наследование для статических классов.



что-то вроде этого:



public static class Base
{
}

public static class Inherited : Base
{
}


не будет работать.



Почему разработчики языка закрыли эту возможность?

616   11  

11 ответов:

цитата из здесь:

Это на самом деле по дизайну. Кажется, нет никаких веских причин наследовать статический класс. Он имеет открытые статические члены, к которым вы всегда можете получить доступ через само имя класса. единственные причины, которые я видел для наследования статического материала, были плохими, например, сохранение нескольких символов ввода.

возможно, есть смысл рассмотреть механизмы приведения статических элементов непосредственно в область (и мы фактически рассмотрим это после цикла продукта Orcas), но наследование статического класса-это не путь: это неправильный механизм для использования и работает только для статических членов, которые находятся в статическом классе.

(Mads Torgersen, C# Language PM)

другие мнения от игры Channel9

наследование в .NET работает только на базе экземпляра. статические методы, определенные на уровень типа не на уровне экземпляра. Вот почему переопределение не работает со статическими методами/свойствами/событиями...

статические методы только один раз в память. Нет виртуальной таблицы и т. д. то, что создано для них.

Если вы вызываете метод экземпляра в .NET, вы всегда даете ему текущий экземпляр. Это скрыто средой выполнения .NET, но это происходит. каждый метод экземпляра имеет в качестве первого аргумента указатель (ссылку) на объект, способ это работает дальше. Это не происходит со статическими методами (как они определены на уровне типа). Как компилятор должен решить выбрать метод для вызова?

(littleguru)

и как ценная мысль, littleguru имеет частичный "обходной путь" для этой проблемы:Синглтон узор.

значит так:

static class Foo { }

компилируется в этот IL:

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

подумайте об этом так: вы получаете доступ к статическим членам через имя типа, например:

MyStaticType.MyStaticMember();

если бы вы унаследовали от этого класса, вам пришлось бы получить к нему доступ через имя нового типа:

MyNewType.MyStaticMember();

таким образом, новый элемент не имеет отношения к оригиналу при использовании в коде. Для таких вещей, как полиморфизм, не было бы никакого способа использовать какие-либо отношения наследования.

возможно, вы думаете, что просто хотите расширить некоторые элементы в исходный класс. В этом случае ничто не мешает вам просто использовать член оригинала в совершенно новом типе.

возможно, вы хотите добавить методы к существующему статическому типу. Вы можете сделать это уже с помощью методов расширения.

возможно, вы хотите, чтобы иметь возможность пройти статическую Type к функции во время выполнения и вызовите метод для этого типа, не зная точно, что делает метод. В этом случае, вы можете использовать интерфейс.

Так, в в конце концов, вы ничего не получаете от наследования статических классов.

то, что вы хотите достичь с помощью иерархии классов может быть достигнуто только через пространство имен. Таким образом, языки, поддерживающие namespappes ( например, C#), не будут использовать реализацию иерархии классов статических классов. Поскольку вы не можете создать экземпляр любого из классов, все, что вам нужно, это иерархическая организация определений классов, которые вы можете получить с помощью пространств имен

вы можете использовать вместо них композицию... это позволит вам получить доступ к объектам класса из статического типа. Но все равно не могу реализовать интерфейсы или абстрактные классы

хотя вы можете получить доступ к "унаследованным" статическим членам через имя унаследованных классов, статические члены на самом деле не наследуются. Отчасти поэтому они не могут быть виртуальными или абстрактными и не могут быть переопределены. В вашем примере, если вы объявили базу.Метод (), компилятор сопоставит вызов с унаследованным.Метод () назад к основанию.Метод () в любом случае. С таким же успехом можно позвонить на базу.Метод () явно. Вы можете написать небольшой тест и посмотреть результат с отражателем.

Так... если вы не можете наследовать статические члены, и если статические классы могут содержать только статические члены, Что хорошего в наследовании статического класса?

Хммм... было бы совсем по-другому, если бы у вас были только нестатические классы, заполненные статическими методами..?

обходной путь, который вы можете сделать, - это не использовать статические классы, а скрыть конструктор, чтобы статические члены классов были единственными доступными вне класса. Результатом является наследуемый "статический" класс по существу:

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>();

к сожалению, из-за ограничения языка" по дизайну " мы не можем сделать:

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

public static class TestClass : TestClass<double>
{
}

вы можете сделать что-то, что будет выглядеть статического наследования.

вот в чем фокус:

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

тогда вы можете сделать это:

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 класс сам по себе не статичен, но мы не позволяем его создавать. Он фактически унаследовал статический конструктор, который строит Base, и все свойства и методы Base доступно как статическое. Теперь осталось только сделать статические обертки для каждого метода и свойства, которые вам нужно выставить на ваш статический контекст.

есть такие недостатки, как необходимость ручного создания статических методов обертки и new ключевое слово. Но этот подход помогает поддерживать то, что действительно похоже на статическое наследование.

С. П. Мы использовали это для создания скомпилированных запросов, и это фактически может быть заменено ConcurrentDictionary, но статическое поле только для чтения с его потокобезопасностью было достаточно хорошим.

статические классы и члены класса используются для создания данных и функций, к которым можно получить доступ без создания экземпляра класса. Статические члены класса могут использоваться для разделения данных и поведения, которые не зависят от идентификатора объекта: данные и функции не изменяются независимо от того, что происходит с объектом. Статические классы могут использоваться, когда в классе нет данных или поведения, зависящих от идентификатора объекта.

класс может быть объявлен static, который указывает, что он содержит только статические члены. Невозможно использовать ключевое слово new для создания экземпляров статического класса. Статические классы будут автоматически загружены .NET и общеязыковой среды выполнения (CLR), когда программа или пространство имен, содержащее класс загружается.

используйте статический класс, чтобы содержать методы, не связанные с определенным объектом. Например, обычно требуется создать набор методов, которые не действуют на данные экземпляра и являются не связан с определенным объектом в коде. Вы можете использовать статический класс для хранения этих методов.

Ниже приведены основные характеристики статического класса:

  1. Они содержат только статические члены.

  2. Они не могут быть инстанцирован.

  3. они запечатаны.

  4. Они не могут содержать конструкторы экземпляров (руководство по программированию на C#).

создание таким образом, статический класс-это в основном то же самое, что и создание класса, содержащего только статические члены и частный конструктор. Частный конструктор предотвращает создание экземпляра класса.

преимущество использования статического класса заключается в том, что компилятор может проверить, не добавлены ли случайно члены экземпляра. Компилятор гарантирует, что экземпляры этого класса не могут быть созданы.

статические классы запечатаны и поэтому не могут быть унаследованы. Они не могут наследовать от любого класса, кроме объекта. Статические классы не могут содержать конструктор экземпляра; однако, они могут иметь статический конструктор. Дополнительные сведения см. В разделе статические конструкторы (руководство по программированию в C#).

когда мы создаем статический класс, который содержит только статические члены и частный конструктор.Единственная причина заключается в том, что статический конструктор предотвращает создание экземпляра класса, для которого мы не можем наследовать статический класс .Единственный способ получить доступ к члену статического класса с помощью самого имени класса.Попытка наследовать статический класс не является хорошей идеей.

Comments

    Ничего не найдено.