Proč nemohu mít abstraktní statické metody v jazyce C #?

hlasů
158

Pracoval jsem s poskytovateli spravedlivý trochu v poslední době, a jsem narazil na zajímavou situaci, kdy jsem chtěl mít abstraktní třídu, která měla abstraktní statické metody. Četl jsem několik příspěvků na toto téma, a to jakýsi smysl, ale je tam pěkná jasné vysvětlení?

Položena 06/08/2008 v 12:04
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
146

Statické metody nejsou instance jako takové jsou prostě k dispozici bez odkazu na objekt.

Volání statické metody se provádí pomocí název třídy, nikoli prostřednictvím odkazu na objekt, a IL kód říkat zavolá abstraktní metodu skrze jméno třídy, která je definována, nemusí být nutně název třídy, kterou jste použili ,

Dovolte mi ukázat příklad.

S následujícím kódem:

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

public class B : A
{
}

Pokud zavoláte B.Test, jako je tento:

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

Pak aktuální kód uvnitř hlavní metoda je následující:

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

Jak můžete vidět, je provedeno volání k A.Test, protože to byl Třída, která je definována, a nikoli na B.Test, i když můžete psát kód, který cestu.

Pokud byste měli typy tříd , jako v Delfách, kde si můžete vytvořit proměnnou odkazující na typu a nikoliv objektu, měli byste mít větší využití pro virtuální a tak abstraktních statické metody (a také konstruktéři), ale nejsou k dispozici, a takto statické hovory jsou non-virtuální v .NET.

Uvědomuji si, že IL návrháři by mohla umožnit kód musí být sestaven tak, aby volání B.Test a vyřešit volání za běhu, ale to ještě nebude virtuální, jak byste ještě muset napsat nějaký název třídy tam.

Virtuální metody, a ty se tak abstraktní, jsou užitečné pouze v případě, že používáte proměnnou, která za běhu, může obsahovat mnoho různých typů objektů, a vy tedy chcete volat tu správnou metodu pro aktuální objekt, který jste v proměnné. Se statickými metodami budete muset projít název třídy stejně, takže přesný způsob volání je znám v době překladu, protože nemůže a nebude měnit.

Tak, virtuální / abstraktní statické metody nejsou k dispozici v .NET.

Odpovězeno 06/08/2008 v 12:30
zdroj uživatelem

hlasů
42

Statické metody nemůže být dědičné nebo potlačena, a to je důvod, proč nemohou být abstraktní. Vzhledem k tomu, statické metody jsou definovány na typu, ne instance třídy, musí být nazýván výslovně na tomto typu. Takže když chcete volat metodu na třídě dítěte, budete muset použít své jméno říkat. To dělá dědictví irelevantní.

Předpokládám, že jste mohli na chvíli, dědí statické metody. Představte si tento scénář:

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; }
}

Pokud zavoláte Base.GetNumber (), která metoda by být nazýván? Jehož hodnota se vrátila? Jeho docela snadné vidět, že bez vytvoření instance objektů, dědičnost je poměrně těžké. Abstraktní metody bez dědictví jsou jen metody, které nemají tělo, takže nelze nazvat.

Odpovězeno 06/08/2008 v 12:21
zdroj uživatelem

hlasů
15

Další respondent (McDowell) uvedl, že polymorfismus funguje pouze pro instancí objektů. To by mělo být kvalifikovaný; existují jazyky, které dělají zacházet tříd jako instance nebo typu „Class“ „Metaclass“. Tyto jazyky nepodporují polymorfismus pro oba stupně a třídy (statické) metody.

C #, jako je Java a C ++ před ním, není tento jazyk; staticklíčové slovo se používá explicitně naznačovat, že metoda je staticky vázané spíše než dynamický / virtual.

Odpovězeno 09/08/2008 v 08:01
zdroj uživatelem

hlasů
8

Zde je situace, kdy je rozhodně potřeba dědictví pro statické pole a metody:

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"?
Odpovězeno 18/02/2010 v 06:36
zdroj uživatelem

hlasů
8

Chcete-li přidat na předchozí vysvětlení, statické volání metody jsou vázány na specifické metody při kompilaci , která spíše vylučuje polymorfní chování.

Odpovězeno 06/08/2008 v 12:24
zdroj uživatelem

hlasů
4

Ve skutečnosti jsme přepsat statické metody (v Delphi), je to trochu ošklivý, ale funguje stejně dobře pro naše potřeby.

Používáme ji, takže třídy mohou mít seznam svých dostupných objektů, aniž by instance třídy, například, máme metodu, která vypadá takto:

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

Je to ošklivé, ale je to nutné, tento způsob, jak můžeme vytvořit instanci jen to, co je potřeba, místo toho, aby všechny třídy instantianted jen na vyhledání dostupných objektů.

Jednalo se o jednoduchý příklad, ale samotná aplikace je aplikace typu klient-server, který má všechny třídy jsou k dispozici jen v jednom serveru, a více různých klientů, které nemusí potřebovat vše server nemá a nikdy nebude potřebovat instance objektu.

Tak je to mnohem snazší udržet než má jeden jiný aplikační server pro každého klienta.

Doufám, že příklad byl jasný.

Odpovězeno 18/08/2008 v 20:01
zdroj uživatelem

hlasů
0

Abstraktní metody jsou implicitně virtuální. Abstraktní metody vyžadují instance, ale statické metody nemají instanci. Takže můžete mít statickou metodu v abstraktní třídě, to prostě nemůže být statický abstrakt (nebo abstraktní statické).

Odpovězeno 14/05/2009 v 12:11
zdroj uživatelem

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