Inheritance is not necessarily the best way to model problems when type instances can change over time.
Instead, you might consider using a composition. Sort of:
class Task
{
private TaskDetail m_Detail;
public TaskDetail Detail { get { return m_Detail; } }
}
abstract class TaskDetail { ... }
class PhoneCallDetail : TaskDetail { ... }
class FaxDetail : TaskDetail { ... }
class EmailDetail : TaskDetail { ... }
Tasks will not change when their task data moves from one type to another. You will also need to implement some utility code to convert between different types of tasks, if necessary.
So, a usage example might look like this:
Task theTask = new Task( ... );
theTask.ConvertToEmail(); // internally establishes this as an email task
EmailDetail detail = (EmailDetail)theTask.Detail;
detail.EmailAddress = "wiley.coyote@acme.com";
theTask.ConvertToFax(); // may transfer or lose some detail...
FaxDetail faxDetail = (FaxDetail)theTask.Detail;
faxDetail.FaxDate = DateTime.Now;
// and so on.
, , , Task , , ; :
Task someTask = ...;
if( someTask.Detail is EmailDetail )
{
EmailDetail detail = (EmailDetail)someTask.Detail;
}
else if( someTask.Detail is FaxDetail )
{
FaxDetail detail = (FaxDetail)someTask.Detail;
}
. , , , .
- , , , , .
, , - . / . . , , .
. ( ), :
abstract class TaskDetail
{
public abstract object this[string key] { get; }
}
public class FaxDetail : TaskDetail
{
public string FaxNumber { get; set; }
public DateTime DateSent { get; set; }
public override object this[string key]
{
get
{
switch( key )
{
case "FaxNumber": return FaxNumber;
case "DateSent": return DateSent;
default: return null;
}
}
}
}
public class EmailDetail : TaskDetail
{
public string EmailAddress { get; set; }
public DateTime DateSent { get; set; }
public override object this[string key]
{
get
{
switch( key )
{
case "EmailAddress": return EmailAddress;
case "DateSent": return DateSent;
default: return null;
}
}
}
}
Task someTask;
object dateSent = someTask.Detail["DateSent"];
if( dateSent != null )