Почему я не могу иметь абстрактные статические методы в C #?

голоса
158

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

Задан 06/08/2008 в 12:04
источник пользователем
На других языках...                            


7 ответов

голоса
146

Статические методы не инстанцированы как таковые, они просто доступны без ссылки на объект.

Вызов статического метода осуществляется через имя класса, а не через ссылку на объект, а код IL назвать это будет вызывать абстрактный метод через имя класса, который определил его, не обязательно имя класса, который вы использовали ,

Позвольте мне показать пример.

С помощью следующего кода:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

Если вы звоните B.Test, как это:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

Тогда фактический код внутри основного метода заключается в следующем:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

Как вы можете видеть, вызов на A.Test, потому что это был класс А, который определил его, а не B.Test, даже если вы можете написать код таким образом.

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

Я понимаю, что дизайнеры IL может позволить код быть скомпилирован для вызова B.Test и разрешить вызов во время выполнения, но он все равно не будет виртуальным, как вы бы все равно придется писать какое-то имя класса там.

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

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

Ответил 06/08/2008 d 12:30
источник пользователем

голоса
42

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

Предположим, вы могли бы на мгновение, наследуют статические методы. Представьте себе такой сценарий:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Если вы звоните Base.GetNumber (), какой метод будет называться? Какое значение возвращается? Его довольно легко видеть, что без создания экземпляров объектов, наследование довольно трудно. Абстрактные методы без наследования только методы, которые не имеют тела, поэтому не могут быть названы.

Ответил 06/08/2008 d 12:21
источник пользователем

голоса
15

Другой респондент (МакДауэлл) говорит, что полиморфизм работает только для экземпляров объектов. Это должно быть квалифицировано; Есть языки, которые делают рассматривать классы как экземпляры одного или типа «класса» «метакласса». Эти языки поддерживают полиморфизм как для экземпляра и (статическая) методы класса.

C #, как Java и C ++ перед ним, не таким языком; staticключевое слово используется для обозначения явно , что метод статический переплета , а не динамических / виртуального.

Ответил 09/08/2008 d 08:01
источник пользователем

голоса
8

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

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?
Ответил 18/02/2010 d 06:36
источник пользователем

голоса
8

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

Ответил 06/08/2008 d 12:24
источник пользователем

голоса
4

Мы на самом деле переопределить статические методы (в Дельфах), это немного некрасиво, но это работает очень хорошо для наших нужд.

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

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

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

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

Так что это гораздо легче поддерживать, чем иметь один другое приложение сервера для каждого клиента.

Надеюсь, что пример был ясен.

Ответил 18/08/2008 d 20:01
источник пользователем

голоса
0

Абстрактные методы неявно виртуальные. Абстрактные методы требуют экземпляра, но статические методы не имеют экземпляр. Таким образом, вы можете иметь статический метод в абстрактном классе, он просто не может быть статической аннотации (или абстрактными статическим).

Ответил 14/05/2009 d 12:11
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more