2017-01-06 2 views
0

Я работаю со старым (.NET 1) API, который я не могу изменить. API не имеет интерфейсов. У меня есть базовый класс (Pet) с конкретными классами (Cat, Parrot), которые имеют по существу «тот же» метод (GetLegs()). Я хочу, чтобы мой вспомогательный класс «отключался» и просто вызывал метод, используя тип экземпляра. Я хочу избежать размышлений.Метод вызова с тем же именем для разных типов

Моя попытка имеет тип включения. Это разумный подход? Должен ли я быть заинтересован (на уровне «теории»), что Type слишком общий?

namespace TheApi 
{ 
    public class Pet 
    { 
    } 

    public class Cat : Pet 
    { 
     public string[] GetLegs() => 
      new[] { "Front left", "Front right", "Back left", "Back right" }; 
    } 

    public class Parrot : Pet 
    { 
     public string[] GetLegs() => 
      new[] { "Left", "Right" }; 
    } 
} 

namespace MyApp 
{ 
    using System; 
    using System.Collections.Generic; 
    using NUnit.Framework; 
    using TheApi; 
    public static class Helper 
    { 
     public static string[] GetLegsFor(Pet pet) 
     { 
      return MapTypeToGetter[pet.GetType()](pet); 
     } 

     private static Dictionary<Type, Func<Pet, string[]>> MapTypeToGetter => 
      new Dictionary<Type, Func<Pet, string[]>> 
      { 
       [typeof(Cat)] = p => ((Cat)p).GetLegs(), 
       [typeof(Parrot)] = p => ((Parrot)p).GetLegs() 
      }; 
    } 

    public class Tests 
    { 
     [Test] 
     public void Test() 
     { 
      Pet bird = new Parrot(); 
      var legs = Helper.GetLegsFor(bird); 

      var expectedLegs = new[] { "Left", "Right" }; 
      Assert.That(legs, Is.EqualTo(expectedLegs)); 
     } 
    } 
} 
+4

вы должны иметь интерфейс - 'IHaveLegs'. –

+4

Почему бы просто не использовать метод расширения на 'Pet'? –

+1

@ DanielA.White OP сказал: Я работаю со старым (.NET 1) API, который я не могу изменить. API не имеет интерфейсов. – CodingYoshi

ответ

2

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

Я бы не стал писать вспомогательный класс. Я бы написать метод расширения:

namespace PetesExtensions 
{ 
    public static class PetExtensions 
    { 
    public static string[] GetLegs(this Pet pet) 
    { 
     if (pet == null) throw new ArgumentNullException("pet"); 
     if (pet is Cat) return ((Cat)pet).GetLegs(); 
     if (pet is Parrot) return ((Parrot)pet).GetLegs(); 
     throw new Exception(
     $"I don't know how to get the legs of a {pet.GetType().Name}. Contact Pete Moloy."); 
    } 
    } 
} 

И тогда вы можете сказать

using PetesExtensions; 
... 
Pet p = whatever; 
string[] legs = p.GetLegs(); 
+0

Привет, Эрик, я пытаюсь пережевывать концепцию ООП. Каково было бы преимущество создания метода расширения v. Интерфейса. Предположим, я хочу создать класс «Worm», который может быть «домашним», но не имеет ног. Разве я не буду лучше использовать интерфейс, чтобы я мог выбрать, какое домашнее животное получает ноги или нет? Благодарю. – Zuzlx

+2

@ Zuzlx: Конечно, было бы лучше. Предпосылка вопроса заключается в том, что использование интерфейса невозможно. Перечитайте первые два предложения вопроса. –

+0

Метод расширения - синтаксический сахар, который я могу добавить к моему. Но ваша оценка действительно отличается от моей, то есть мы оба включаем тип, нет? – petemoloy

Смежные вопросы