Reputation: 278
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:
As opposed to this:
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
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
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
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
.
(Sorry for the crude diagram, I only had MS Paint available right now.)
Upvotes: 6
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