2009-03-02 10 views
11

In C#, ho un prodotto di classe base e un widget di classe derivata.C#: come si chiama un metodo statico di una classe base da un metodo statico di una classe derivata?

Il prodotto contiene un metodo statico MyMethod().

Voglio chiamare il metodo statico Product.MyMethod() dal metodo statico Widget.MyMethod().

Non riesco a utilizzare la parola chiave di base, perché funziona solo con i metodi di istanza.

Posso chiamare Product.MyMethod() in modo esplicito, ma se successivamente cambio Widget per derivare da un'altra classe, devo rivedere il metodo.

C'è qualche sintassi in C# simile alla base che mi consente di chiamare un metodo statico da una classe base da un metodo statico di una classe derivata?

+1

Qualsiasi motivo per cui questo particolare metodo è statico? – Rad

risposta

16

static i metodi sono fondamentalmente un metodo di ripiego dai concetti orientati agli oggetti. Di conseguenza, non sono molto flessibili nelle gerarchie di ereditarietà e non è possibile fare una cosa del genere direttamente.

La cosa più vicina che riesco a pensare è una direttiva using.

using mybaseclass = Namespace.BaseClass; 

class MyClass : mybaseclass { 

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

} 
+4

> I metodi statici sono fondamentalmente un metodo di riserva ... Perché è vero? Nel codice per la mia classe, i metodi che si basano su dati di istanza sono metodi di istanza. I metodi che non si basano su dati di istanza, ma si basano solo sui parametri (se presenti) sono metodi statici. Trovo utile questa distinzione. – MindModel

+0

Un metodo che non si basa su un'istanza * object * non viene riprodotto dalla maggior parte delle regole definite per gli oggetti (metodo virtual dispatching, ...). –

+0

mindmodel, mentre ci sono alcuni scenari per questo, se inizi ad avere bisogno dell'ereditarietà o [inserisci qualsiasi altra restrizione rispetto ai metodi non statici] è un sintomo che qualcos'altro potrebbe essere fuori ... forse la classe ha troppe responsabilità – eglasius

0

Avere in conto che un metodo statico shoudn't relè in dati di istanza ... si dovrebbe avere un "MyMethod" statica che si comporta Diferent sulla base di un parametro o qualcosa di simile.

Ricorda che il metodo statico definito in una classe è solo un modo per ordinare il tuo codice ... ma è lo stesso se quel metodo è collocato altrove ... perché non si inoltra sull'oggetto dove è posto.

EDIT: Penso che il tuo migliore scelta è quella di utilizzare in modo esplicito Product.MyMethod ... Se si pensa che ... è should't essere probabile che il vostro widget cambiare la sua classe di base ... e anche in quella caso si tratta di un piccolo cambiamento nel codice.

+0

Non completamente vero. i metodi statici possono fare affidamento su membri privati ​​di un tipo (sia statici che istanza), di conseguenza, non sono completamente mobili. –

+0

Vero. Conoscete la differenza tra variabili statiche (una per classe) e variabili di istanza (una per istanza). Perché questa distinzione non è utile? Perché è un cattivo design OO? – MindModel

+0

Beh, avrei dovuto dire che "non dovresti" non inoltrare dati di istanza variabili ... ovviamente "PUOI". :) – Romias

1

I metodi statici non sono polimorfici, quindi ciò che si vuole fare è impossibile.

Provare a trovare un modo per trattare i metodi statici come polimorfici è possibile ma pericoloso, perché il linguaggio stesso non lo supporta.

Alcuni suggerimenti:

4

Si può fare, ma io non lo consiglio.

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); 
    } 
} 
+4

Abbastanza giusto. In questo caso, la soluzione è peggiore del problema. Grazie. – MindModel

+0

Esattamente. Dieci caratteri – marcumka

+2

nstead di utilizzare la stringa che è possibile utilizzare MethodBase.GetCurrentMethod(). Nome –

0

I metodi statici sono metodi "di classe". Sono intesi come metodi che si applicano a tutte le istanze di una classe specifica. Pertanto, l'ereditarietà di questo metodo non ha senso in quanto cambierebbe il significato da applicare alle istanze della classe. Ad esempio, se si eseguiva il looping di una raccolta di prodotti (alcuni di Widget, altri no) e si chiamava MyMethod su ciascun prodotto, il metodo chiamato veniva determinato dall'istanza della classe. Questo viola lo scopo dei metodi statici.

Probabilmente si può fare qualcosa come si desidera in modo più pulito semplicemente non usando affatto metodi statici, perché nel proprio esempio non sembra che MyMethod si applichi a tutte le istanze di Prodotto. Tuttavia, è possibile ottenere lo stesso effetto che si sta descrivendo utilizzando una classe di interfaccia come "IMyMethod". Questo approccio non utilizza ancora un metodo statico. Immagino di non vedere il bisogno di un metodo statico. Perché vuoi usare un metodo statico per cominciare?

4

La chiamata di un metodo statico mediante riflessione è esattamente la stessa di un metodo di istanza, tranne che si passa il null per l'istanza. Hai bisogno di FlattenHierarchy perché è definito in un antenato.

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

Ulteriore lettura e il pensiero mi lascia le stesse domande come gli altri che hanno risposto: perché usare metodi statici come questo? Stai cercando di fare una programmazione funzionale, e se è così, perché non usare le espressioni lambda? Se vuoi comportamenti polifonici con stato condiviso, i metodi di istanza sarebbero migliori.

-1

È molto semplice. Molto più semplice dell'utilizzo di alias, riflessioni, ecc. Forse è stato reso più facile con le aggiunte più recenti di .NET, IDK, ma questo funziona perfettamente bene. Proprio come con i metodi di istanza, l'accesso ai metodi di base non richiede l'utilizzo di base, è facoltativo, in genere necessario quando la classe ereditaria e quella di base hanno un metodo con lo stesso nome. Anche senza la parola chiave base, puoi accedere ai metodi statici di una classe base come se fossero nella classe da cui stai chiamando. Ho provato questo solo quando si chiama un metodo statico statico dal metodo statico statico di una classe derivata. Potrebbe non funzionare se si chiama da un metodo di istanza a un metodo statico.

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

Aaron, OP ha lo stesso nome di metodo per le classi di base e derivate. Insieme al fatto che lei non vuole specificare "Base.StaticMethod' in modo esplicito, questi due sono il nocciolo del problema. – nawfal

2

In primo luogo, se siete preoccupati per ri-genitorialità una classe, allora probabilmente stai facendo eredità sbagliato. L'ereditarietà dovrebbe essere usata per stabilire relazioni "is-a", non semplicemente per riutilizzare il codice adottivo. Se è necessario riutilizzare il codice da solo, considerare l'utilizzo della delega piuttosto che l'ereditarietà. Suppongo che potresti introdurre un tipo intermedio tra un sottotipo e il suo genitore, ma lascerei che questa possibilità guidasse il mio progetto.

In secondo luogo, se è necessario utilizzare le funzionalità dalla classe base ma estenderlo E il caso d'uso richiede un metodo statico, è possibile prendere in considerazione l'utilizzo di alcune classi esterne per mantenere la funzionalità. Il classico caso per questo nella mia mente è il modello Factory. Un modo per implementare il modello Factory è tramite Metodi Factory, un metodo statico su una classe che costruisce un'istanza di quella classe. Solitamente il costruttore è protetto in modo che il metodo factory sia l'unico modo per costruire la classe dall'esterno.

Un modo per avvicinarsi al riutilizzo con i metodi di fabbrica in una gerarchia di ereditarietà sarebbe inserire il codice comune in un metodo protetto e chiamare tale metodo dal metodo di fabbrica piuttosto che chiamare direttamente il metodo di base della classe di base da un tipi Metodo di fabbrica. Un'implementazione migliore potrebbe utilizzare la stessa tecnica, ma spostare i metodi di fabbrica su una classe Factory e utilizzare la logica del costruttore (interna ora, non privata), forse in combinazione con un metodo di inizializzazione, per creare l'oggetto. Se il comportamento che si sta ereditando è esterno alla classe (decifrazione/validazione/ecc.), È possibile utilizzare metodi condivisi (o composizione) all'interno della Factory per consentire il riutilizzo tra i metodi Factory.

Senza conoscere l'obiettivo del tuo utilizzo dei metodi statici è difficile darti una direzione esatta, ma speriamo che ciò possa essere d'aiuto.

2

si può fare:

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

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

può essere utile per i metodi statici protetti di unit test (per esempio).

Problemi correlati