2010-09-14 2 views
2

J'ai trois classes qui retourneront chacune un résultat légèrement différent.Comment avoir une méthode abstraite retourne un type abstrait avec des implémentations concrètes?

// interfact to a king 
public interface IKing{ 
    public Result Get(); 
} 

// main abstract class 
public abstract class King:IKing{ 
    public abstract Result Get(); 
} 

// main abstract result 
public abstract class Result{ 
    public int Type {get;set;} 
} 

// KingA result 
public class ResultA:Result{ 
    ... 
} 

// KingB result 
public class ResultB:Result{ 
    ... 
} 

// concrete implementations 
public class KingA:King{ 
    public override ResultA Get(){ 
    return new ResultA; 
    } 
} 

public class KingB:King{ 
    public override ResultB Get(){ 
    return new ResultB 
    } 
} 

Cela ne fonctionnera pas depuis la King méthode surchargée de Get attend la classe Result et n'acceptera pas ses enfants ResultA et ResultB.

Y a-t-il une meilleure approche que je peux prendre?

+0

Une chose que je n » De la même manière, il est nécessaire que les classes appelant le code doivent être conscientes de la distribution, puis s'assurer que la méthode a renvoyé la bonne classe de résultats. L'utilisation de génériques résout ces problèmes. – Kenoyer130

Répondre

4

L'approche habituelle consiste à utiliser des génériques.

public interface IKing<T> where T:Result{ 
    T Get(); 
} 

public class King<T> : IKing<T> 
    public abstract T Get(); 
} 

public class KingA : King<ResultB> { 
    public override ResultA Get(){ 
     return new ResultA(); 
    } 
} 

public class KingB : King<ResultB> { 
    public override ResultB Get(){ 
     return new ResultB(); 
    } 
} 

Édition: syntaxe fixe.

+2

"vous ne pouvez pas faire de méthodes abstraites qui remplacent une définition d'interface". Je suis d'accord que cela peut être redondant, mais il compile bien. Cependant, le code OP (et votre version) a plusieurs erreurs de compilation, y compris les parens manquantes et une définition de classe foirée. –

+0

J'ai fini par retourner ceci et utiliser une classe abstraite au lieu d'une interface, puisque je voulais des propriétés communes de toutes les classes "King". Le concept clé de l'utilisation de génériques était ce que je cherchais cependant. Merci! – Kenoyer130

0

Vous devriez être en mesure de jeter explicitement ResultA et ResultB comme Result dans les implémentations de Get (je suppose que ce que les « réalisations concrètes » sont destinées à être).

1

Cela vous aidera si vous utilisez du code qui compile. Vos «implémentations concrètes» sont fausses, on dirait que vous avez mélangé les concepts de classe et de méthode. Il n'y a pas de problème de conception ici. Par exemple:

public class KingA : King { 
    public override Result Get() { 
     return new ResultA(); 
    } 
} 
1

Je pense qu'il ya une certaine confusion de syntaxe ici - si je saisis bien votre intention, cela fonctionne très bien:

// interface to a king 
public interface IKing 
{ 
    Result Get(); 
} 

// main abstract class 
public abstract class King : IKing 
{ 
    public abstract Result Get(); 
} 

// main abstract result 
public abstract class Result 
{ 
    private int _Type; 
    public int Type { get { return _Type; } set { _Type = value; } } 
} 

// KingA result 
public class ResultA : Result 
{ 

} 

// KingB result 
public class ResultB : Result 
{ 

} 

// concrete implementations 
public class KingA : King 
{ 
    public override Result Get() 
    { 
     return new ResultA(); 
    } 
} 

public class KingB : King 
{ 
    public override Result Get() 
    { 
     return new ResultB(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IKing ka = new KingA(); 
     IKing kb = new KingB(); 

     Result ra = ka.Get(); 
     Result rb = kb.Get(); 

     if (ra is ResultA) 
     { 
      Console.WriteLine("A ok!"); 
     } 

     if (rb is ResultB) 
     { 
      Console.WriteLine("B ok!"); 
     } 
    } 
} 

(modifié pour le formatage)

Questions connexes