I'm trying to figure out how to make a method in a base abstract class capable of using member values of instantiated objects derived from the class. For example, let's say I have a class called Vehicle
that inherits an interface called IVehicle
;
public abstract class Vehicle : IVehicle
{
public int Wheels = 4;
public int CountWheels()
{
return Wheels;
}
}
Let's say I then had another class called Motorcycle
that inherited Vehicle
as such;
public class Motorcycle : Vehicle, IVehicle
{
public int Wheels = 2;
}
If I make a new Motorcycle
called newMotorcycle
and I call newMotorcycle.CountWheels()
, I get 4 instead of 2. I'm assuming this is an issue with my Wheels
definition in the Motorcycle
class, but I've tried just about everything I can think of to get this to work and it always seems to want to ignore child class definitions. I know that I could make the CountWheels()
method abstract and define it in the Motorcycle
class, but I'm trying to keep the base Vehicle
class as generic as possible so I can implement a ton of other child classes without having to redefine the same method over and over.
My first question; is what I'm trying to do even possible? If so, what part of my member definition needs to change for this to work the way I'm intending for it to?
I promise I scoured the internet before I posted this here and I couldn't find enough information to help myself...
You will notice that there is a warning in the code you posted:
Motorcycle.Wheels hides inherited member Vehicle.Wheels...
Hence your problem, Vehicle
has no idea that a derived class has hidden one of its members (hence why hiding is a bad idea).
Since you can't have virtual fields, you should change it to a virtual (or in this case, abstract so everyone has to define it) property :
public abstract class Vehicle : IVehicle
{
public abstract int Wheels {get;}
public int CountWheels()
{
return Wheels;
}
}
public class Motorcycle : Vehicle, IVehicle
{
public int Wheels => 2;
}
Now every derived class will have to have a Wheels
property that the base class can use.
You need to make the Wheels
member virtual
and override
it, otherwise you're just "hiding" the base member. You'll also need to change it to a property in order to make it virtual
:
public abstract class Vehicle
{
public virtual int Wheels { get { return 4; } }
public int CountWheels()
{
return Wheels;
}
}
public class Motorcycle : Vehicle
{
public override int Wheels { get { return 2; } }
}
Look up virtual
properties and methods ( https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx )
You need Wheels
to be public virtual int Wheels {get; set;}
public virtual int Wheels {get; set;}
in base and public override int Wheels {get; set;}
public override int Wheels {get; set;}
in derived
Then you can initialize the value as you need in each class.
Here's another option. Rather than defining Wheels
as a virtual property on Vehicle
, and overriding that property on Motorcycle
, you can define Wheels
as an ordinary property and then set it in the constructor for Motorcycle
:
public abstract class Vehicle : IVehicle
{
public int Wheels { get; protected set; }
public Vehicle()
{
Wheels = 4;
}
public int CountWheels()
{
return Wheels;
}
}
public class Motorcycle : Vehicle, IVehicle
{
public Motorcycle()
{
Wheels = 2;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.