Qual é a melhor maneira para herdar uma matriz que precisa para armazenar subclasse específica de dados?

StackOverflow https://stackoverflow.com/questions/31088

Pergunta

Eu estou tentando configurar uma hierarquia de herança semelhante à seguinte:

abstract class Vehicle
{
  public string Name;
  public List<Axle> Axles;
}

class Motorcycle : Vehicle
{
}

class Car : Vehicle
{
}

abstract class Axle
{
  public int Length;
  public void Turn(int numTurns) { ... }
}

class MotorcycleAxle : Axle
{
  public bool WheelAttached;
}

class CarAxle : Axle
{
  public bool LeftWheelAttached;
  public bool RightWheelAttached;
}

Eu gostaria de armazenar apenas MotorcycleAxle objetos em uma Motocicleta objeto de Eixos da matriz, e CarAxle objetos em um Carro do objeto Eixos da matriz.O problema é que não existe nenhuma maneira de substituir a matriz na subclasse para forçar um ou outro.Idealmente algo como o seguinte seria válido para a Motocicleta classe:

class Motorcycle : Vehicle
{
  public override List<MotorcycleAxle> Axles;
}

mas os tipos de jogo, quando o substituir.Como posso apoiar esta arquitetura?Eu vou ter que fazer um monte de tipo de tempo de execução e verificação de fundição onde os Eixos membro é acessado?Eu não gosto de adição de tipo de tempo de execução verifica porque você começa a perder os benefícios de escrever forte e polimorfismo.Há que ter pelo menos algumas verificações em tempo de execução neste cenário desde o WheelAttached e Esquerda/RightWheelAttached propriedades dependem do tipo, mas eu gostaria de minimizá-los.

Foi útil?

Solução

Usar mais genéricos

abstract class Vehicle<T> where T : Axle
{
  public string Name;
  public List<T> Axles;
}

class Motorcycle : Vehicle<MotorcycleAxle>
{
}

class Car : Vehicle<CarAxle>
{
}

abstract class Axle
{
  public int Length;
  public void Turn(int numTurns) { ... }
}

class MotorcycleAxle : Axle
{
  public bool WheelAttached;
}

class CarAxle : Axle
{
  public bool LeftWheelAttached;
  public bool RightWheelAttached;
}

Outras dicas

2 opções de primavera para a mente.1 é o uso genéricos:

abstract class Vehicle<TAxle> where TAxle : Axle {
   public List<TAxle> Axles;
}

O segundo utiliza o sombreamento - e isso pressupõe ter propriedades:

abstract class Vehicle {
   public IList<Axle> Axles { get; set; }
}

class Motorcyle : Vehicle {
   public new IList<MotorcycleAxle> Axles { get; set; }
}

class Car : Vehicle {
   public new IList<CarAxle> Axles { get; set; }
}

void Main() {
   Vehicle v = new Car();
   // v.Axles is IList<Axle>

   Car c = (Car) v;
   // c.Axles is IList<CarAxle>
   // ((Vehicle)c).Axles is IList<Axle>

O problema com o sombreamento é que você tem uma Lista genérica.Infelizmente, você não pode se restringir a lista para conter apenas o CarAxle.Além disso, você não pode conjurar uma Lista<Axle> na Lista<CarAxle> - mesmo que há uma cadeia de heranças lá.Você tem que associar cada objeto em uma nova Lista (apesar de que fica muito mais fácil com o LINQ).

Gostaria de ir para os genéricos mim.

Perguntei a um semelhante pergunta e tem uma resposta melhor, o problema está relacionado a C#'s suporte para a covariância e contravariância.Veja-se que a discussão um pouco mais de informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top