views:

303

answers:

14

I am working with insurance and have two different policy types - motor and household, represented by two different classes, Motor and Household.

Both have several bits of data in common, so both would inherit from another class called Policy. When a user logs into the app, they could have either a motor or a household policy, so the app needs to display the generic information and the information unique to Motor or Household. To encapsulate all this, i have a response object that has both a Motor member and a Household member, as shown below:

public class Response
{
    ...
    private MotorPolicy                 _motorPolicy;
    private HouseholdPolicy             _householdPolicy;
    ....
}

The code below should demonstrate:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{
    lblDescription.Text = response.MotorPolicy.Description;
    lblReg.Text = response.MotorPolicy.Reg;
}
else
{
    lblDescription.Text = response.HouseholdPolicy.Description;
    lblContents.Text = response.HouseholdPolicy.Contents;
}

The MotorPolicy doesn't have Contents property and the HouseholdPolicy doesn't have a Reg property.

But I really want to simply do:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{
    lblDescription.Text = response.Policy.Description;
    ...
}

I have tried using generics, could couldn't find the right solution. Can anyone help?

Thanks in advanced.

A: 

define the Policy interface and implement it in your both the policy classes

Interface IPolicy{
    int Reg {get;set;};
    string Contents {get;set;};
}

MotorPolicy : Policy,IPolicy {

 string IPolicy.Contents 
     {get;set;};


 int IPolicy.Reg 
     {get;set;};

}

HouseholdPolicy : Policy , IPolicy {
 string IPolicy.Contents 
     {get;set;};


 int IPolicy.Reg 
     {get;set;};
}
Ramesh Vel
He has a baseclass called Policy, using a interface instead would change nothing.
jgauffin
That's not really how I understand good oo design. Household policies don't have a reg number, and motor policies don't have contents. Therefore the design is misleading
Dave Arkell
OK.. then he can OP can define like this another way.. MotorPolicy : Policy, IPolicy
Ramesh Vel
Ramesh, how would that work inheriting from both the base class and the interface?
Chris
Chris, i have updated the answer... check out
Ramesh Vel
A: 

The simplest solution would be to implement an interface with a description property and a "contents" property, and then in your motor policy class, create a dummy "contents" property which returns "reg".

Nellius
+5  A: 

Your response only needs a Policy type, you can then store a MotorPolicy or HouseholdPolicy type into it.

Then your response just needs to check for data type

if (response.Policy is MotorPolicy) ....

Alternatively have an abstract method or a property returning data from an abstract method on the Policy type that is fully inplemented by the child classes and returns reg data or contents data as apporpriate.

ChrisBD
codekaizen
He could also create a Dictionary<Type, Action<Policy>> which maps each policy type to a seperate handler method.
jgauffin
+1  A: 
public interface IPolicy
{
    string Description { get; }
    string Reg { get; }
    string Contents { get; }
}

public class MotorPolicy : IPolicy
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return ...; }
    }

    public string Contents
    {
        get { return String.Empty; }
    }
}

public class HousholdPolicy : IPolicy
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return String.Empty; }
    }

    public string Contents
    {
        get { return ...; }
    }
}

public class Response
{
    ...
    private IPolicy             _policy;
    ....
}

Now you don't need an Enumeration to show which type you've implemented, you can just say

lblDescription.Text = response.Policy.Description;
lblReg.Text = response.Policy.Reg;
lblContents.Text = response.Policy.Contents;

Edit: Alternate solution

public interface IPolicy
{
    string Description { get; }
}

public interface IHasReg
{
    string Reg { get; }
}

public interface IHasContents
{
    string Contents { get; }
}

public class MotorPolicy : IPolicy, IHasReg
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return ...; }
    }
}

public class HouseholdPolicy : IPolicy, IHasContents
{
    public string Description
    {
        get { return ...; }
    }

    public string Contents
    {
        get { return ...; }
    }
}

public class Response
{
    ...
    private IPolicy             _policy;
    ....
}

This leaves you with more code in the calling function

lblDescription.Text = response.Policy.Description;
IHasReg hasReg = response.Policy as IHasReg;
if (hasReg != null) lblReg.Text = hasReg.Reg;
IHasContents hasContents = response.Policy as IHasContents;
if (hasContents != null) lblContents.Text = hasContents.Contents;

but is considerably more extensible than other options presented and complies with your desire to avoid functionality in the implementation which doesn't make sense.

pdr
This is what i thought to start with, but just didn't like how my householdPolicy would contain Reg, and MotorPolicy would contain Contents. Would really like to have a policy object that, based on the data obtained, would have just one or the other.
Chris
@Chris - I would look at that the other way around. Your Response NEEDS a description, a reg and contents, thus any Policy implementation should provide that data, hence the interface. The concrete implementations deliberately return String.Empty in the fields that don't apply to that type of policy.
pdr
A: 

Can your response contain either a MotorPolicy or a HouseholdPolicy or, can it contain one of each?

If you are dealing with one or the other then create a base type that both classes inherit that defines the common properties. When you output the common properties just cast the Policy as the base type and use that.

Scott Rickman
It does contain both a HouseholdPolicy and a MotorPolicy, but then i have to refer to even my description as response.MotorPolicy.Description and response.HouseholdPolicy.Description for common properties. I realy want to just have response.Policy.Description so i am not nearly duplicating code.
Chris
nice answer..........
Nishant
A: 

My immediate thought is to go for:

public abstract class Response
{
  public abstract Policy Policy {get;}//can be used for stuff for dealing with all policies.
  public static Response GetResponse(Policy policy)
  {//factory method
    if(policy is MotorPolicy)
      return new MotorResponse((MotorPolicy)policy);
    if(policy is HouseholdPolicy)
      return new HouseholdResponse((HouseholdPolicy)policy);
    throw new ArgumentException("Unexpected policy type");
  }
}
public class MotorResponse : Response
{
  private readonly MotorPolicy _motorPolicy;
  public MotorResponse(MotorPolicy policy)
  {
    _motorPolicy = policy;
  }
  protected override Policy Policy
  {
    get { return _motorPolicy; }
  }
  // motor specific stuff
}
public class HouseholdResponse : Response
{
  private readonly HouseholdPolicy _householdPolicy;
  public HouseholdResponse(HouseholdPolicy policy)
  {
    _householdPolicy = policy;
  }
  protected override Policy Policy
  {
    get { return _householdPolicy; }
  }
  // household specific stuff
}
Jon Hanna
nice question..............
Nishant
Why do you favor explicit fields etc. instead of using a generic base class?
Lucero
I don't, but i am not that familiar with generics, especially using them as base classes, and i couldn't get that solution to work. Do you know how??
Chris
@Lucero, I wouldn't argue for generics here (based on what we know of the problem), because right now what commonality I can see as useful in Response depends upon the commonality in policy, and if I was to have `Response<T> where T:Policy` then I'd still have to derive from `Response<HouseholdPolicy>` to provide the extras needed. Really, a generic base class doesn't add much extra, and then it does block any runtime polymorphism.
Jon Hanna
If i went with this solution, then wouldn't i just have two different types of response objects, so i'd be back in the situation i am in now, except with response instead of policy.
Chris
@Jon, that was the problem i cam across when i tried a generic solution.
Chris
No, you can call `response.Policy.Description` and it works either way. You have a choice of staying with the test when it comes to `lblContents` (nasty in most cases), having HouseholdPolicy return an empty string for `Contents` (well, it **should** clear that bit of the form) or having an abstract `Display()` method that gets overridden in each case (seems like overkill here and more work than its worth, but in some similar cases it can be the way to go, e.g. if you needed each to produce a chunk of HTML for a web app).
Jon Hanna
That said, you'll notice there is still some switching and if-else going on in the factory method. The advantage though is it pushes it all into one place, rather than littering the rest of the code.
Jon Hanna
A: 

I would try something like this:

  public class Response
  {
     public Policy SelectedPolicy {get;set;}

     //I don't think you need these, but hard to 
     //say without seeing the rest of the code
     ...
     private MotorPolicy                 _motorPolicy;
     private HouseholdPolicy             _householdPolicy;
     ....
  }

then

lblDescription.Text = response.SelectedPolicy.Description;

if (SelectedPolicy is MotorPolicy)
    lblReg.Text = ((MotorPolicy)response.SelectedPolicy).Reg;

else if (SelectedPolicy is HouseholdPolicy)
    lblContents.Text = ((HouseholdPolicy)response.SelectedPolicy).Contents;

I would not put both Reg and Contents in the base class or interface. If I do what's the purpose of inheritance if all classes look the same? The only benefits I would get would be types, and that's not going to gain me much in this case.

Angelok
+5  A: 

Each Policy descendant (now you have two, you might have more in the future, right?) should have their own UI controls which "know" how to deal with the policy information. The same approach can be used for other things, such as a "controller" for policy objects etc.

The response can then be made generic:

public class Response<T> where T: Policy {
    ...
    private T _policy;
    ....
}

Alternatively, you could have a more generic approach which uses reflection to display the information, but those are usually less "sexy" in their appearance and usability (think of the Property Grid in the VS designer).

Lucero
I agree with the UI controls.
Mike
A: 

maybe I don't understand the question but I would just use inheritence

define policy as

public class Policy { public string Description{ get; set;} public string Details {get; set;}

}

public class MotorPolicy:Policy 
{
    public void SetReg(string reg)
    {
        base.Details = reg;
    }
}

public class HousePolicy:Policy 
{
    public void SetContents(string contents)
    {
        base.Details = contents;
    }
}

and call by

    private void Form1_Load(object sender, EventArgs e)
    {
        MotorPolicy mp = new MotorPolicy();
        mp.Description = "Motor";
        SetForm(mp);       
    }

    private void SetForm(Policy p)
    {
        lblDescription.Text = p.Description;
        lblDetail.Text = p.Details;

        //then if you still need specifics 
        if (p.GetType() == typeof(MotorPolicy))
        {
            MotorPolicy mp = p as MotorPolicy;
            //continue assigning mp
        }
        else if (p.GetType() == typeof(HousePolicy))
        {
            HousePolicy hp = p as HousePolicy;
            //continue assigning Hp
        }
    }

Note I put reg/contents as a field detail as they are both string types. If one was int vs string then they would have to be done separate.

Mike
+1  A: 

One option is to add a member to Policy that synthesizes all the derived class' relevant properties to provide a summary:

 public abstract class Policy {
     public string Description { get; set; }
     public abstract string Summary { get; }
 }

 public class MotorPolicy: Policy {
     public override string Summary {
         get { return this.Description + "\r\n" + this.Reg; }
     }
 }

 public class HouseholdPolicy: Policy {
     public override string Summary {
         get { return this.Description + "\r\n" + this.Contents; }
     }
 }

This centralizes the logic and makes the user interface code simple:

 label.Description.Text = response.Policy.Summary;

That basic implementation sacrifices the ability to format the subsections separately. You could overcome that by exposing the summary as a collection of strings:

public abstract IEnumerable<string> SummarySections { get; }

If you want to display the derived classes' details in fundamentally different ways, you'll have to embrace the conditional logic in the user interface layer (for example, you might list the household policy's contents in a table, but show a scanned image for the motor policy's registration).

Jeff Sternal
+1  A: 

Use the template pattern:

Create a base class called Policy with a virtual abstract get method to determine the description of the policy.

public abstract class Policy
{ 
    protected virtual string GetDescription()
    {
         return string.Empty()    
    }

    public string Description 
    { 
        get 
        {
           return GetDescription();
        } 
    }
}

public MotorPolicy : Policy
{
    public override string GetDescription()
    {
       return ..... ////specific description implementation for MotorPolicy
    }
}

public HouseHoldPolicy : Policy
{
    public override string GetDescription()
    {
       return ..... ////specific description implementation for HouseholdPolicy
    }
}


public class Response        
{        
    ...        
    private MotorPolicy                 _motorPolicy;        
    private HouseholdPolicy             _householdPolicy; 
    private PolicyType                  _policyType;       
    ....        

    public Policy Policy
    {
        get
        {
           if (_policyType== PolicyType.Motor) 
           {
              return _motorPolicy;
           } 
           if (_policyType== PolicyType.Household) 
           {
              return _householdPolicy;
           } 

           return null;
        }
    }        
}    

client code:

if (response.Policy != null)        
{       
    lblDescription.Text = response.Policy.Description;       
    ...       
}    

Let MotorPolicy and HouseholdPolicy derive from Policy and override the abstract get method from the base and create a specific implementation of it.

In the Response class just get the description.

Patrick Peters
A: 

Yours is a unique example of "Refactoring condition to Polymorphism" [Fowler].

And then your method should accept the proper object and do as below:

public void Update(IPolicy policy)
{
        lblDescription.Text = policy.Description;
        lblReg.Text = .Reg;

}
Amby
A: 

What about below , you can create virtual property in the bae policy class and override this property in derived classes.

   class Program
{
 static void Main(string[] args)
    {

        PolicyType temp = default(PolicyType);
        // here 1 can be replaced with some string also "Motor", "HouseHold"
        Enum.TryParse<PolicyType>("1",out temp);

        Policy userPolicy = PolicyCreator.CreatePolicy(temp);
        Console.WriteLine(userPolicy.Description);
    }


}

public enum PolicyType
{
    Motor = 1,
    HouseHold
}

public abstract class Policy
{

    public virtual string Description { get; set; }
}

public class MotorPolicy : Policy
{
    public override string Description
    {
        get
        {
            return base.Description;
        }
        set
        {
            base.Description = value;
        }
    }
}


public class HouseHoldPolicy : Policy
{
    public override string  Description
    {
          get 
        { 
             return base.Description;
        }
          set 
        { 
            base.Description = value;
        }
    }
}




public class PolicyCreator
{
    public static Policy CreatePolicy(PolicyType type)
    {
        Policy temp = null;
        if (type == PolicyType.HouseHold)
        {
            temp = new HouseHoldPolicy();
            temp.Description = "HouseHold";
            return temp;
        }

        if (type == PolicyType.Motor)
        {
            temp = new MotorPolicy();
            temp.Description = "Motor";
            return temp;
        }   

        return temp;
    }
}
saurabh
A: 

Well, I dislike abstract classes so I went with an interface for Policy

public interface IPolicy
{
    string Description { get; set;}
    void Display();
}

Then we inherit from it to create MotorPolicy

public class MotorPolicy : IPolicy
{
    public string Description { get; set; }
    public string Reg { get; set; }

    public void Display()
    {
        Console.WriteLine(string.Format("Description: {0}", Description));
        Console.WriteLine(string.Format("Reg: {0}", Reg));
    }
}

Then for response I changed the Policy to a List in the off chance that you can have both or either. Now we've offloaded the handling of displaying the data to the specific policy itself.

public class Response
{
    public List<IPolicy> Policies { get; set; }

    public void Display()
    {
        Policies.ForEach(p => p.Display());
    }

    public void Display(Type t)
    {
        var policy = (from p in Policies
                      where p.GetType() == t
                      select p).FirstOrDefault();
        policy.Display();
    }
}

This could easily be changed to not use the List and we can get rid of the overloaded Display.

Howel