3

I have an interface Vehicle implemented by a two classes Car and Truck. how do i create an array of interface type containing a mixture of all the different classes and still be able to access their members, and change them

public interface Vehicle
{
    double purchase_price();
    string vehicle_type();
    int release_year();
    int purchase_year();
    bool IsOld(int releaseYear, int purchaseYear);
    void Details();

}

In my main method i have this

  var vehls = new Vehicle[]
       {
           new Truck(8, 1000, "Ford", "F15000", 2011, 2016, false),
           new Truck(4, 13000, "Ford", "F-150", 2009, 2014, false),
           new Car("Ford", "Super Duty", 2012, 2017, false),
       };

when i try to access the car members to assign them it doesn't allow me. it gives me error.

   Car c1 = vehls[2];   
   c1.Wheel = 4;
   c1.Miles = 12000;

unless i cast them:

   Car c1 = (Car) vehls[2];
   c1.Wheel = 4;
   c1.Miles = 12000;

How will i be able to create such an array so that i can still be able to access each class member and fields, without filling everything in the constructor. I don't want to be casting it all the time. Is there a way that the assignment will be able to detect the class type automatic and allow me to access and assign members?

Seek Addo
  • 1,871
  • 2
  • 18
  • 30

2 Answers2

8

No, there isn't.

This is the whole point of using interfaces (or base classes for that matter), that you only access the derived classes through the interface. If you need access to Wheel and Miles then those members should be part of the interface (as a property).

Downcasting like you are doing is a major code-smell, while you can't always avoid it, its a good sign you are doing something the wrong way.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • what is the solution for this, i mean good design would be what? – Ehsan Sajjad Mar 10 '17 at 17:32
  • @EhsanSajjad I don't know your whole domain model so its hard to say. As a commentor pointed out, trucks have wheels and mileage too so for this *exact* code I would just add those two properties to the interface – BradleyDotNET Mar 10 '17 at 17:33
  • Thanks for your comments. so basically all the methods are in the interface and there is no need creating properties for them when implementing them in each class – Seek Addo Mar 10 '17 at 17:36
  • @SeekAddo Yes... and no. All public methods/properties (basically) belong in the interface. Implementing classes *still* need those properties in order to conform to the interface though. – BradleyDotNET Mar 10 '17 at 17:38
  • @BradleyDotNET yes, i add all the miles, wheels, and manufacturer in the Interface, and implemented them in the classes. But my point is, all methods are from the interface and there is nothing more for each class to define. is that normal with Interfaces? – Seek Addo Mar 10 '17 at 17:40
  • If you are asking if it is normal for classes to not have public members beyond an interface they implement, yes; that is quite common for classes that implement interfaces. This is especially true when the class is a implementation of a Strategy pattern or similar since their only use is going to be through that interface – BradleyDotNET Mar 10 '17 at 17:44
  • I realise the question has much more detail beyond the title, however if one were to simply answer the title and without concern for the wrongs or rights of best practice, it can be achieved. E.g. `var myarray = new List().ToArray();` Don't hate me ;) – David Savage Nov 30 '18 at 10:51
1

It sound more like you have an architecture issue. According to Liskov Substitution Principle, where ever you are using you're interface you should be treating it like an interface and not trying to downcast it to a specific type.

If you need to handle those issues separately, then either create two lists, and concat them to an interface list later. Or delegate a better way of handle this, using some factory pattern or adapter pattern etc.

Resource for Liskov Substition Principle

Resource for Factory Pattern

Community
  • 1
  • 1
johnny 5
  • 19,893
  • 50
  • 121
  • 195