Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a derived class using only code in the base class?

I was recently posed this programming problem and failed to solve it. I was asked to write a subclass that could be inherited so that the below code could function correctly. Here's the catch, the base class (I named it Party) is the only one that can contain code for Find().

var address = new Address("56 Main St", "Town", "AZ", "12345");
var customer = new Customer("John", "Doe", address);
var company = new Company("Town Company", address);

Customer savedCustomer = Customer.Find(customer.Id);
Company savedCompany = Company.Find(company.Id);

Party is hidden. Customer and Company both inherit it.

How could I have caused Party to return Customer and Company when called from one of those classes? I was told it's possible using generics but that I can't change the calls to look like Find<Company>(customer.Id). However, all the resources I examined say you can't return derived types from a base class.

EDIT: I solved it by have Customer.Find() and Company.Find() call Party.partyFind() and then cast the result to their type. I submitted the solution along with the explanation:

I tried to keep the Find functionality in the base class as much in the base class as possible but I wasn't sure how to return derived types from a single base class without generics (which would require modifying the test code anyway)

I received the reply:

You're mistaken, generics can solve this problem without modifying the test code; specializing Find at the call site as Find<Customer> is not allowed. You have more to learn about generics.

like image 573
sirdank Avatar asked Dec 22 '25 04:12

sirdank


1 Answers

Just looking at your update, what the person was talking about was probably specializing Party:

public class Party<T>
{
    public static T Find(int id)
    {
         ...
    }
}

public class Customer : Party<Customer>{}
public class Company : Party<Company>{}

This can then indeed call Find statically on derived classes without passing the generic type to the Find method explicitly.

var cust = Customer.Find(1); // returns instance of Customer
var comp = Company.Find(2); // returns instance of Company

Live example: http://rextester.com/GPDFI94766

like image 175
Jamiec Avatar answered Dec 23 '25 19:12

Jamiec