W kodzie C #, jeśli klasa Rebar pochodzi z klasy Reinforcement i klasy RebarShape dziedziczy klasę ReinforcementShape. Czy można zastąpić właściwość ReinforcementShape w klasie bazowej za pomocą klasy RebarShape?

   public class ReinforcementShape
   {
   }

   public class RebarShape : ReinforcementShape
   {
   }

   public class Reinforcement
   {
        public ReinforcementShape Shape { get; set; }
   }


   public class Rebar : Reinforement
   {
        // I want to override the Shape property
        // but with its derived class which is RebarShape

        // override the base property somehow!
        public RebarShape Shape { get; set; }
   }

Aktualizacja:

Co jest nie tak z bieżącą implementacją?

w bazie:

public virtual ReinforcementShape Shape { get; set; }

po uzyskaniu:

public new RebarShape Shape { get; set; }
5
Vahid 16 luty 2017, 11:43

2 odpowiedzi

Najlepsza odpowiedź

Możesz to zrobić za pomocą generycznych, nie ma potrzeby zastępowania członka klasy bazowej:

public class Reinforcement<T> where T: ReinforcementShape 
{
    public <T> Shape { get; set; }
}

public class Rebar : Reinforement<RebarShape>
{
}

Teraz możesz łatwo utworzyć instancję ReBar i uzyskać dostęp do jego Shape - właściwość, która jest instancją RebarShape:

var r = new Rebar();
r.Shape = new RebarShape();

Próba przypisania instancji ReinforcementShape do tej właściwości spowoduje błąd czasu kompilacji, w tym momencie jest ważny w tym momencie tylko RebarShape.

Edytuj: zgodnie z edycją. Możesz zastąpić członka, nadpisując go do wdrożenia, a nie wartości zwrotu. Tak więc użycie virtual nie zrobi nic w twoim przypadku. Jednak jako już wspomniano o R.ruv już potrzebujesz tylko new - słowa kluczowego na elemencie pochodnym, co faktycznie zapewni całkowicie nowy członek, który ma taką samą nazwę, jak ta z klasy bazowej. Ale w rzeczywistości jest to zupełnie inny członek, który nic wspólnego z pierwszym. Jednak po napisaniu następujących

Reinforcement r = new Rebar();
// assign value to Shape
var shape = r.Shape;

Pierwotna implementacja jest używana, a nie nowa. Więc shape byłby typu ReinforcementShape zamiast RebarShape. Jedynym sposobem na to jest zadeklarowanie r jako Rebar w pierwszej kolejności:

Rebar r = new Rebar();
// assign value to Shape
var shape = r.Shape;

Ale to dość mylące do każdego użytkownika aplikacji i może również sam. Generly nie polecam używania tego słowa kluczowego. Lepiej użyj pierwszego podejścia.

8
HimBromBeere 16 luty 2017, 09:09

Możesz użyć słowa kluczowego new, aby to zrobić. Więc twoja definicja klasy REBAR będzie tak wyglądać.

public class Rebar : Reinforement
{
    public new RebarShape Shape
    {
        get { return (RebarShape)base.Shape; }
        set { base.Shape = value; }
    }
}
1
R.Rusev 16 luty 2017, 08:48