2013-06-11 14 views
12

Mam starszy kod przy użyciu BaseClass, a kod oczekuje, że customerid będzie typu int. Następnie mam wymóg utworzenia nowej klasy, DerivedClass, która zachowuje się bardzo podobnie do BaseClass, ale teraz customerid musi być łańcuchem. Starszego kodu nie można zmodyfikować, aby nie było potrzeby testowania.Czy istnieje sposób użycia właściwości o tej samej nazwie, ale jest innego typu w klasie pochodnej?

Jak uzyskać pożądany efekt przy użyciu dziedziczenia (lub w jakikolwiek inny sposób)?

Kod testu Linqpad poniżej pokazuje, co muszę zrobić. Oczywiście nie skompiluje się, ponieważ customerid w DerivedClass musi być int. Potrzebuję również właściwości string o nazwie customerid. Musi to być ta nazwa, ponieważ inny kod użyje tej klasy zamiast BaseClass i oczekuje, że ta sama nazwana właściwość będzie ciągiem typu.

public class BaseClass 
{ 
    public virtual int customerid {get; set;} 

    public void printname() 
    { 
     customerid = 1; 
     customerid.Dump(); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override string customerid {get; set;} 

    public void PrintCustomerID() 
    { 
     customerid = "jshwedeX"; 
     customerid.Dump(); 
    } 
} 



void Main() 
{ 
    DerivedClass dc = new DerivedClass(); 
    dc.printname(); 
} 
+3

Czy możesz użyć [jawnej implementacji interfejsu] (http://msdn.microsoft.com/en-us/library/vstudio/ms173157.aspx)? – millimoose

+0

W przypadku programistów VB należy użyć słowa kluczowego "Cienie" podczas tworzenia nowej definicji właściwości, pola itp. Może to mieć wpływ na programowanie dynamiczne podczas rzutowania na typ nadrzędny, jeśli wartości zwracane są niezgodne. – ps2goat

Odpowiedz

21

Można użyć modyfikatora new tak:

public class BaseClass 
{ 
    public virtual int customerid {get; set;} 

    public void printname() 
    { 
     customerid = 1; 
     customerid.Dump(); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new string customerid {get; set;} 

    public void PrintCustomerID() 
    { 
     customerid = "jshwedeX"; 
     customerid.Dump(); 
    } 
} 

To daje pożądanych rezultatów, ale również ukryć obiekt w klasie bazowej. Jeśli odwołujesz się do instancji DerivedClass jako zmiennej BaseClass, możesz odwołać się do właściwości w klasie bazowej; nie klasa pochodna.

Innymi słowy:

BaseClass instance = new DerivedClass(); 
string customerId = instance.customerid; // <- this won't compile 

Alternatywą byłoby użycie jawne implementacje interfejsu:

public interface IBase 
{ 
    int customerid { get; set; } 
} 

public interface IDerived 
{ 
    string customerid { get; set; } 
} 

public class Derived : IBase, IDerived 
{ 
    int IBase.customerid { get; set; } 
    string IDerived.customerid { get; set; } 
} 

Gdy instancja Derived jest przechowywany w zmiennej typu IBase, customerid rozwiąże się wersja int, a gdy jest przechowywana w zmiennej typu IDerived, zostanie rozwiązana do wersji string:

var derived = new Derived(); 
IBase ibase = derived; 
IDerived iderived = derived; 
int id1 = ibase.customerid; // <- compiles just fine 
string id2 = iderived.customerid; // <- compiles just fine 

Można również użyć rzucania:

var instance = new Derived(); 
int id1 = ((IBase)instance).customerid; 
string id2 = ((IDerived)instance).customerid; 

pamiętać, że jawne implementacje interfejsu spowodować realizowane członkowie nie będzie widoczny, chyba że zmienna jest typu interfejsu:

var instance = new Derived(); 
var customerid = instance.customerid; // <- this won't compile 
+1

+1 preferują jawny interfejs ukrywając znaczenie bazy –

Powiązane problemy