Thanasi Poulos
Thanasi Poulos

Reputation: 278

Having issues addressing inheritance in C#

I'm having some trouble understanding how to implement inheritance.

My model is purely for demonstration's sake, but here we go:

I have a Parent Class Bus. It has two children DieselBus and ElectricBus. These are abstract classes.

I have a further two classes Coach and CityBus. How do I set those up to inherit from either DieselBus OR ElectricBus without having to define separate Coach and CityBus classes like CoachDieselBus, CoachElectricBus, CityBusDieselBus and CityBusElectricBus ? Is that even feasible/possible?

I don't have examples short of just some skeletons so far, looking for advice on this point.

What I am looking for is this: Correct

As opposed to this: Incorrect

Thanks!

EDIT (2013-07-03):

First, some code:

Bus.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InheritanceTest {
    abstract class Bus {
        public Bus () {

        }

        public abstract Engine EngineType {
            get;
            set;
        }

        private int id;
        public int ID {
            get {
                return id;
            }
            set {
                id = value;
            }
        }

        private int seats;
        public int Seats {
            get {
                return seats;
            }
            set {
                seats = value;
            }
        }

        private float length;
        public float Length {
            get {
                return length;
            }
            set {
                length = value;
            }
        }

        private String colour;
        public String Colour {
            get {
                return colour;
            }
            set {
                colour = value;
            }
        }
    }
}

Coach.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InheritanceTest {
    class Coach : Bus {
        public Coach (int id, int seats, float length, String colour, String company, Engine engine) {
            this.ID = id;
            this.Seats = seats;
            this.Length = length;
            this.Colour = colour;
            this.EngineType = engine;
            this.company = company;
        }

        public override Engine EngineType {
            get;
            set;
        }

        private String company;
        public String Company {
            get {
                return company;
            }
            set {
                company = value;
            }
        }

        public override string ToString () {
            return (this.ID + "\t" + this.Seats + "\t" + this.Length + "\t" + this.Colour + "\t" + this.Company + "\t" + this.EngineType.ToString ());
        }
    }
}

Engine.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InheritanceTest {
    abstract class Engine {
        public Engine () {

        }

        private float power;
        public float Power {
            get {
                return power;
            }
            set {
                power = value;
            }
        }

        private float torque;
        public float Torque {
            get {
                return torque;
            }
            set {
                torque = value;
            }
        }

        private int redline;
        public int Redline {
            get {
                return redline;
            }
            set {
                redline = value;
            }
        }
    }
}

DieselEngine.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InheritanceTest {
    class DieselEngine : Engine {
        public DieselEngine (float power, float torque, int redline, float displacement, float fuelEconomy) {
            this.Power = power;
            this.Torque = torque;
            this.Redline = redline;
            this.displacement = displacement;
            this.fuelEconomy = fuelEconomy;
        }

        private float displacement;
        public float Displacement {
            get {
                return displacement;
            }
            set {
                displacement = value;
            }
        }

        private float fuelEconomy;
        public float FuelEconomy {
            get {
                return fuelEconomy;
            }
            set {
                fuelEconomy = value;
            }
        }

        public override string ToString () {
            return "Diesel Engine";
        }
    }
}

I'm having a problem in my program execution:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InheritanceTest {
    class Program {
        static void Main (string[] args) {
            String line;
            var diesel = new DieselEngine (200F, 550F, 3500, 7.5F, 10F);
            var electric = new ElectricEngine (85F, 1000F, 19000, 24F, 65000F);
            var city = new CityBus (124, 75, 18.5F, "Red", "Brisbane", electric);
            var coach = new Coach (777, 120, 22.5F, "Blue", "GreyHound", diesel);
            line = new String ('-', city.ToString ().Length * 2);

            System.Console.WriteLine ("City Buses\n\nID\tSeats\tLength\tColour\tCity\t\tEngine Type");
            System.Console.WriteLine (line);
            System.Console.WriteLine (city.ToString ());

            System.Console.WriteLine ("\n\nCoach Buses\n\nID\tSeats\tLength\tColour\tCompany\t\tEngine Type");
            System.Console.WriteLine (line);
            System.Console.WriteLine (coach.ToString ());

            System.Console.ReadKey (true);
        }
    }
}

No matter how I try to, I cannot access any of the properties of either of the classes that inherit engine from their relevant buses. For example, I cannot see the Displacement of the DieselEngine I gave to Coach "coach."

Upvotes: 2

Views: 166

Answers (4)

WiiMaxx
WiiMaxx

Reputation: 5420

Here are an example of how you could do what you want

public abstract class Engine
{
    public abstract string Name { get; set; }
}

public class DieselEngine:Engine
{
    public override string Name { get; set; }

    public string DieselEngineProperty { get; set; }
}

public class ElectricEngine : Engine
{
    public override string Name { get; set; }

    public string ElectricEngineProperty { get; set; }
}

public class HybridEngine : Engine
{
    public override string Name { get; set; }

    public string HybridEngineProperty { get; set; }
    public List<Engine> EngineList { get; set; }
}



public abstract class Bus
{
    public abstract string Name { get; set; }
    public abstract string Lengh { get; set; }
    public abstract Engine BusEngine { get; set; }
}

public class CoachBus: Bus
{
    public override string Name { get; set; }

    public string CoachBusProperty { get; set; }
}

public class CityBus:Bus
{

    public override string Name { get; set; }
    public override string Lengh { get; set; }
    public override Engine BusEngine { get; set; }

    public string CityBusProperty { get; set; }
}

and here are some buses

        var myDieselEngine = new DieselEngine();
        myDieselEngine.Name = "TöffTöff";

        var myElectricEngine = new ElectricEngine();
        myDieselEngine.Name = "SumSum";

        var myHybridEngine = new HybridEngine();
        myDieselEngine.Name = "SumTöff";

        var myDieselCityBus = new CityBus();
        myDieselCityBus.Name = "Shorty1";
        myDieselCityBus.Lengh = "5 m";
        myDieselCityBus.BusEngine = myDieselEngine;

        var myElectricCityBus = new CityBus();
        myElectricCityBus.Name = "Shorty2";
        myElectricCityBus.Lengh = "7 m";
        myElectricCityBus.BusEngine = myElectricEngine;

        var myHybridCoachBus = new CoachBus();
        myHybridCoachBus.Name = "Shorty2";
        myHybridCoachBus.Lengh = "15 m";
        myHybridCoachBus.BusEngine = myHybridEngine;

Upvotes: 1

TomTom
TomTom

Reputation: 62093

As usual when this question arrives, the confusion starts with an unfeasible class tree. I personally would say that none of them is an inheritance issue.

A bus has an engine, which is a base class for DieselEngine and ElectricEngine.

A bus has a Usage which is base class for City and Coach, possibly.

Using inheritance here is a classical antipattern. A typical beginner mistake - so do not feel bad about it. The result are mostly way too complex inheritance trees.

You may alternatively use interfaces (IDieselEngine, IElectricEngine) but I would probably go with composition.

Upvotes: 2

Heinzi
Heinzi

Reputation: 172210

I have a further two classes Coach and CityBus. How do I set those up to inherit from either DieselBus OR ElectricBus without having to define separate Coach and CityBus classes like CoachDieselBus, CoachElectricBus, CityBusDieselBus and CityBusElectricBus ? Is that even feasible/possible?

No, that's not feasible. The inheritance relation must be fixed, so a Coach must always have the same parent classes.

The appropriate solution for your problem would be to use composition instead of inheritance: Coach and CityBus both inherit from Bus. Bus has an Engine property, which can be set to either a DieselEngine or an ElectricEngine.

Diagram

(Sorry for the crude diagram, I only had MS Paint available right now.)

Upvotes: 6

Szymon
Szymon

Reputation: 43023

In C#, you can only inherit from one class, so only classes shown in the second diagram are possible.

You could use interfaces as a class can implement more than one interfaces but interfaces should really be used more to define behaviour rather then properties/qualities of classes and diesel/electric and city/coach seem more like properties of your buses.

Upvotes: 1

Related Questions