C #: как вызвать статический метод базового класса из статического метода производного класса? - PullRequest
15 голосов
/ 02 марта 2009

В C # у меня есть базовый класс Product и производный класс Widget.

Продукт содержит статический метод MyMethod ().

Я хочу вызвать статический метод Product.MyMethod () из статического метода Widget.MyMethod ().

Я не могу использовать ключевое слово base, потому что это работает только с методами экземпляра.

Я могу явно вызывать Product.MyMethod (), но если позже я изменю Widget для получения из другого класса, мне придется пересмотреть метод.

Есть ли какой-нибудь синтаксис в C #, похожий на base, который позволяет мне вызывать статический метод из базового класса из статического метода производного класса?

Ответы [ 9 ]

18 голосов
/ 02 марта 2009

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

Самая близкая вещь, о которой я могу подумать, это директива using.

using mybaseclass = Namespace.BaseClass;

class MyClass : mybaseclass {

  static void MyMethod() {  mybaseclass.BaseStaticMethod();  }

}
4 голосов
/ 03 июля 2012

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

var type = assy.GetType("MyNamespace.MyType");
MethodInfo mi = type.GetMethod("MyStaticMethod", 
  BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
mi.Invoke(null, null);

Дальнейшее чтение и размышления заставляют меня задавать те же вопросы, что и другие, которые ответили: зачем использовать статические методы, подобные этому? Вы пытаетесь заниматься функциональным программированием, и если да, то почему бы вместо этого не использовать лямбда-выражения? Если вам нужны полиморфные поведения с общим состоянием, лучше использовать методы экземпляров.

4 голосов
/ 02 марта 2009

Это может быть сделано, но я не рекомендую это.

public class Parent1
{
    public static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public new static void Foo()
    {
        Type parent = typeof(Child).BaseType;
        MethodInfo[] methods = parent.GetMethods();
        MethodInfo foo = methods.First(m => m.Name == "Foo");
        foo.Invoke(null, null);
    }
}
3 голосов
/ 24 сентября 2014

Это можно сделать:

public class Parent1
{
    protected static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public static void Foo()
    {
        return Parent1.Foo();
    }
}

Может быть полезно для модульного тестирования защищенных статических методов (например).

2 голосов
/ 07 января 2013

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

Во-вторых, если вам нужно использовать функциональность из базового класса, но расширять его И использовать сценарии использования для статического метода, то вы можете рассмотреть возможность использования некоторого внешнего класса для хранения функциональности. Классический случай для этого, на мой взгляд, это шаблон Factory. Одним из способов реализации шаблона Factory является использование фабричных методов, статического метода класса, который создает экземпляр этого класса. Обычно конструктор защищен, поэтому метод фабрики является единственным способом создания класса извне.

Один из способов приблизиться к повторному использованию с фабричными методами в иерархии наследования - поместить общий код в защищенный метод и вызвать этот метод из фабричного метода, а не напрямую вызывать фабричный метод базового класса из подтипов. Заводской метод. Лучшая реализация может использовать ту же технику, но переместить Методы Фабрики в класс Фабрики и использовать логику конструктора (внутреннюю теперь, а не частную), возможно, в сочетании с методом (ами) инициализации, чтобы создать объект. Если наследуемое вами поведение является внешним по отношению к классу (дешифрование / проверка / и т. Д.), Вы можете использовать общие методы (или композицию) в пределах Factory, чтобы разрешить повторное использование между методами Factory.

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

1 голос
/ 02 марта 2009

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

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

Некоторые предложения:

0 голосов
/ 15 декабря 2012

Это очень просто. Гораздо проще, чем использование псевдонимов, отражений и т. Д. Возможно, это было сделано проще в новых дополнениях .NET, IDK, но это прекрасно работает. Как и в случае с методами экземпляра, для доступа к базовым методам не требуется использовать base, это необязательно, обычно это необходимо, когда у наследуемого и базового класса есть метод с одинаковым именем. Даже без ключевого слова base вы можете получить доступ к статическим методам базового класса, как если бы они были в классе, из которого вы вызываете. Я проверял это только при вызове базового статического метода из метода static производного класса. Может не работать, если вы вызываете метод instance для статического метода.

public class BaseThings
{
    protected static void AssertPermissions()
    {
        //something
    }
}

public class Person:BaseThings
{
    public static void ValidatePerson(Person person)
    {
        //just call the base static method as if it were in this class.
        AssertPermissions();            
    }
}
0 голосов
/ 03 марта 2009

Статические методы являются методами уровня класса. Они предназначены для использования в качестве методов, которые применяются ко всем экземплярам определенного класса. Таким образом, наследование этого метода не имеет смысла, так как это изменило бы значение, применяемое к экземплярам класса. Например, если вы просматривали коллекцию продуктов (некоторые из Widget, некоторые нет) и вызывали MyMethod для каждого продукта, то вызываемый метод будет определяться экземпляром класса. Это нарушает назначение статических методов.

Вы, вероятно, можете сделать что-то вроде того, что хотите более аккуратно, просто вообще не используя статические методы, потому что в вашем примере не похоже, что MyMethod применяется ко всем экземплярам Product. Тем не менее, вы можете достичь того же эффекта, который вы описываете, используя класс интерфейса, такой как «IMyMethod». Этот подход все еще не использует статический метод. Думаю, я не вижу необходимости в статическом методе. Почему вы хотите использовать статический метод для начала?

0 голосов
/ 02 марта 2009

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

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

РЕДАКТИРОВАТЬ: Я думаю, что ваш лучший выбор - это явно использовать Product.MyMethod ... Если вы так думаете ... не должно быть вероятности, что ваш виджет изменит свое базовое условие ... и также в этом случае это незначительное изменение в коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...