С#, реализовать "статические абстрактные" методы
Недавно я столкнулся с проблемой, когда мне кажется, что мне нужен "статический абстрактный" метод. Я знаю, почему это невозможно, но как я могу обойти это ограничение?
Например, у меня есть абстрактный класс, который имеет строку описания. Поскольку эта строка является общей для всех экземпляров, она помечена как статическая, но я хочу, чтобы все классы, полученные из этого класса, предоставляли свое собственное свойство Description, поэтому я обозначил его как абстрактный:
abstract class AbstractBase
{
...
public static abstract string Description{get;}
...
}
Он не будет компилироваться, конечно. Я думал об использовании интерфейсов, но интерфейсы могут не содержать сигнатуры статических методов.
Должен ли я сделать это просто нестатическим и всегда получать экземпляр, чтобы получить эту информацию о конкретном классе?
Любые идеи?
Ответы
Ответ 1
Объединение статичных и абстрактных несколько бессмысленно, да. Идея статики - не нужно представлять экземпляр класса для использования данного члена; однако с абстрактным, каждый ожидает, что экземпляр будет иметь производный класс, который обеспечивает конкретную реализацию.
Я могу понять, почему вам нужна такая комбинация, но факт - единственный эффект, который будет отрицать использование использования 'this' или любых нестатических членов. То есть родительский класс будет определять ограничение в реализации производного класса, даже если нет никакого основного различия между вызовом абстрактного или "статического абстрактного" члена (так как для этого потребуется конкретный пример, чтобы выяснить, какую реализацию использовать)
Ответ 2
Вы не можете.
Место для этого - с атрибутами.
Например,
[Name("FooClass")]
class Foo
{
}
Ответ 3
Если он статичен, есть только один экземпляр переменной, я не вижу, как наследование имеет смысл, если мы сможем сделать то, что вы хотите выполнить со статическими варами в производных классах. Лично я думаю, что вы собираетесь далеко не попробовать экземпляр var.
Почему бы не просто классический способ?
abstract class AbstractBase
{
protected string _Description = "I am boring abstract default value";
}
class Foo : AbstractBase {
public Foo() {
_Description = "I am foo!";
}
}
Ответ 4
Если вы не против откладывать реализации, чтобы разумно реализовать свойство Description, вы можете просто сделать
public abstract string ClassDescription {get; }
// ClassDescription is more intention-revealing than Description
И реализация классов будет делать что-то вроде этого:
static string classDescription="My Description for this class";
override string ClassDescription { get { return classDescription; } }
Затем ваши классы должны следовать контракту о наличии описания, но вы оставляете его для них, чтобы сделать это разумно. Нет способа указать реализацию в объектно-ориентированном режиме (за исключением жестоких, хрупких хаков).
Однако, на мой взгляд, это описание представляет собой метаданные класса, поэтому я бы предпочел использовать механизм атрибутов, как описывали другие. Если вас особенно беспокоит многократное использование рефлексии, создайте объект, который отражает ваш атрибут, и сохраните словарь между типом и описанием. Это минимизирует отражение (кроме проверки времени выполнения, что не так уж плохо). Словарь может быть сохранен как член любого класса, который, как правило, нуждается в этой информации, или, если клиенты по всему домену требуют его, через одноэлементный или контекстный объект.
Ответ 5
Это не статично, если его нужно вызвать в экземпляре.
Если вы не вызываете его в экземпляре, тогда нет никакого полиморфизма в игре (то есть ChildA.Description полностью не связан с ChildB.Description в отношении языка).
Ответ 6
Вы можете сделать "абстрактный" базовый метод throw Exception
, поэтому разработчик "предупреждается", если он пытается вызвать этот метод на дочернем классе без переопределения.
Недостатком является то, что можно расширить класс и не использовать этот метод. Затем обратитесь к другим предоставленным ответам.