I am probably doing something way wrong here, but I have a Base class with multiple derived classes.
public abstract class BaseItem : MonoBehaviour
{
public void LevelUp()
{
// do some common thing ... maybe increase damage
}
}
public class RangedWeapon: BaseItem
{
public new void LevelUp()
{
base.LevelUp();
// do specific things here... maybe increase range.
}
}
public class MeleeWeapon: BaseItem
{
public new void LevelUp()
{
base.LevelUp();
// do specific things here...
}
}
In an inventory manager, I have a list of all items, and can call the LevelUp method on them. The issue, I think, is that I have a list of <BaseItem>s and the specific classes LevelUp is not called:
public void LevelUpItem(string itemName)
{
var item = AvailableItems.First(w => w.ItemName.Equals(itemName));
item.LevelUp();
}
My original thought is that I need to upcast the item before calling the LevelUp function. My second thought is that I'm doing something way wrong here.
My specific question is "How do I upcast safely" and my unasked question is, "should I consider a different approach to polymorphism?"
In C# you can use virtual keyword (also there is abstract modifier in case you don't want to have any default implemenation) for polymorphism:
public abstract class BaseItem : MonoBehaviour
{
public virtual void LevelUp()
{
// do some common thing ... maybe increase damage
}
}
And use override modifier to change the behavior in inheritors:
public class RangedWeapon: BaseItem
{
public override void LevelUp()
{
base.LevelUp();
// do specific things here... maybe increase range.
}
}
Related
This is my first time posting here and I'm rather new to programming, so I might not be fully understanding concepts which I intend to make use of such as interfaces or polymorphism.
I'm currently building a little game in which the player can select different types of objects and I'm struggling with coming up with a robust selection system. The way it works now is through an interface, which is implemented by every type of object the player can select.
public interface ISelectable
{
void DoSomething();
}
Then, this interface is used to call the implemented methods on the current selection based on different events such as mouse clicks or keys pressed.
public class Selector
{
public ISelectable selection;
public PerformAction()
{
selection.DoSomething();
}
}
The methods are implemented in different ways depending on the type of object. However, I've come across certain situations where I don't need a type of object to respond to an event, thus not needing to implement the method defined on the interface.
public class ObjectType1 : ISelectable
{
public void DoSomething() { /*Implemented*/ };
}
public class ObjectType2 : ISelectable
{
public void DoSomething() { /*Not needed*/ };
}
This has led me to believe that this may not be a correct approach to this. Therefore, I have a few questions:
Can my approach be fixed or improved so that it makes more sense and I don't encounter the situation described before again?
If not, is there a "correct" or simpler way to do this kind of selection system?
Thank you in advance. I will try to respond as fast as possible if any further clarification is needed.
Why does your ObjectType2 implement the interface ISelectable? You can remove it when it does not need it.
Or if you want a general interface, you can try these interface definitions:
public interface ISomeEmptyInterface
{
}
public interface ISelectable : ISomeEmptyInterface
{
void DoSomething();
}
Change the selector class:
public class Selector
{
public ISomeEmptyInterface myObj;
public void PerformAction()
{
if(myObj is ISelectable)
{
(myObj as ISelectable).DoSomething();
}
}
}
Classes implement the individual interface:
public class ObjectType1 : ISelectable
{
public void DoSomething()
{
Console.WriteLine("ObjectType1 is called");
};
}
public class ObjectType2 : ISomeEmptyInterface
{
// no any implementation
}
A simple program:
Selector sel1 = new Selector();
sel1.myObj = new ObjectType1();
sel1.PerformAction();
// output "ObjectType1 is called"
Selector sel2 = new Selector();
sel2.myObj = new ObjectType2();
sel2.PerformAction();
// not thing happened
This disadvantage is that your Selector must know what other sub ISomeEmptyInterface interfaces are.
DoSomething(Car car);
DoSomething(Bike bike);
public class Car : Vehicle {}
public class Bike : Vehicle {}
public abstract class Vehicle {}
void run(Vehicle vehicle) {
DoSomething(vehicle);
}
This feels like a simple problem but I'm having issues. DoSomething(Vehicle vehicle) doesn't exist, so DoSomething(vehicle) throws an error, even though vehicle is "guaranteed" to be either Car or Bike. How can I convince the compiler that "vehicle" is Bike or Car, so that DoSomething can be run?
Of course I could just have another method along the lines of
DoSomething(Vehicle vehicle)
{
if(vehicle is Car) ... etc
}
But surely there is a cleaner approach?
EDIT/CLARITY
The motivation for putting this code in a manager class, rather than having DoSomething() exist in the Vehicle class, is that each Vehicle needs to access different parts of the program. For example:
DoSomething(Car car) {
motorwayInfo.CheckMotorwayStatus();
}
DoSomething(Bike bike) {
cycleInfo.CheckCyclePathStatus();
}
Not sure if this analogy is really getting across my particular issue that well, hah - but basically I don't want Car's to have any reference to cycleInfo, nor Bikes to have any reference to motorWayInfo. But, putting DoSomething into Vehicle basically means its parameter needs to either be:
DoSomething(CycleInfo cycleInfo, MotorwayInfo motorwayInfo)
or
DoSomething(InfoManager infoManager)
Neither of which seem totally ideal, as I know that each subtype is only going to use a specific info object. Am I going about this all wrong?
The real question here is - what do you expect to happen to the method's parameter? If that, whatever it is, depends on a concrete (sub)type of the parameter, then the proper place for that behavior is in the virtual (or even abstract) member of the parameter base class - Vehicle.
class Vehicle
{
public abstract void Behave();
}
class Car : Vehicle
{
public override void Behave()
{
// Do something specific to a car
}
}
class Bike : Vehicle
{
public override void Behave()
{
// Do something specific to a bike
}
}
...
void Run(Vehicle vehicle)
{
vehicle.Behave();
}
As you can see from this code, I have reverted the roles. The Run function is not responsible to know how a concrete parameter should behave. Instead, each concrete object passed as the Vehicle parameter would have to know how to behave. That is the proper polymorphism.
Regarding the Run method, all its responsibilities regarding the argument should relate to the common type of all parameter objects, and that is the base class Vehicle. In that respect, the method could access members defined on the base class, or insert the object into a collection, etc.
void Run(Vehicle vehicle)
{
vehicle.Behave();
List<Vehicle> list = ...
list.Add(vehicle);
}
What you're looking for is called Double Dispatch and is not supported natively by the C# compiler.
You can achieve it with some refactoring though:
public void DoSomething(Car car) {}
public void DoSomething(Bike bike) {}
public abstract class Vehicle
{
// ...
public abstract void CallDoSomething();
}
public class Car : Vehicle
{
public override void CallDoSomething()
{
DoSomething(this);
}
}
public class Bike : Vehicle
{
public override void CallDoSomething()
{
DoSomething(this);
}
}
Or, if you don't care about the performance penalty, you can use the dynamic keyword that will defer the overload resolution until runtime then chooses the most appropriate method that matches the type:
void run(dynamic vehicle)
{
DoSomething(vehicle);
}
See MSDN
vehicle is "guaranteed" to be either Car or Bike
That's not true. If all Cars are Vehicles and all Bikes are Vehicles, that does not mean that all Vehicles are either Bikes or Cars. Subtyping does not work that way.
How can I convince the compiler that "vehicle" is Bike or Car, so that DoSomething can be run?
The only way to do that is by casting, which you already mentioned:
if (vehicle is Car) (vehicle as Car).CheckMotorwayStatus();
else if (vehicle is Bike) (vehicle as Bike).CheckCyclePathStatus();
But surely there is a cleaner approach?
The approach that Zoran's answer suggested is the cleaner approach.
I don't want Car's to have any reference to cycleInfo, nor Bikes to have any reference to motorWayInfo.
With some thought, you can use it even with your slightly more complex setup. For example:
public abstract class Vehicle
{
public abstract void PrintRouteStatus();
}
public class MotorwayInfo
{
}
public class CycleInfo
{
}
public class Car : Vehicle
{
// probably pass this in via a constructor.
public MotorwayInfo _motorwayInfo = new MotorwayInfo();
public override void PrintRouteStatus()
{
Console.WriteLine(_motorwayInfo);
}
}
public class Bike : Vehicle
{
// probably pass this in via a constructor.
public CycleInfo _cycleInfo = new CycleInfo();
public override void PrintRouteStatus()
{
Console.WriteLine(_cycleInfo);
}
}
It works without Car being aware at all of Bike's info and vice versa.
public static void Main()
{
var p = new Program();
p.DoSomething(new Car());
p.DoSomething(new Bike());
}
public void DoSomething(Vehicle v)
{
v.PrintRouteStatus();
}
I'm surprised none of these answers included generics or interfacing. Instead of overriding subclass methods per instance, you can reverse this and create a single instance that accepts either.
public abstract class Vehicle {}
public class Car : Vehicle {}
public class Bike : Vehicle {}
public void DoSomething<T>(T _vehicle) where T : Vehicle
{
// _vehicle can be an instance of Car or Bike
if (_vehicle is Car _car)
motorwayInfo.CheckMotorwayStatus();
if (_vehicle is Bike _bike)
cycleInfo.CheckCyclePathStatus();
}
You could take this a step further and implement an IVehicle interface.
FWIW, I wrote what I coined as the "DoubleDispatchObject" to help solve this type of problem - notably,
1) without losing type safety (or resorting to the use of the dynamic keyword, be it at call sites or callees),
2) without burden on the choice of base classes (instead, the simple composition pattern is enough),
and 3) incurring only a couple lines of boilerplate.
here's what your scenario looks like, with it:
public class VehicleManager
{
// boilerplate start
private DoubleDispatchObject dispatch;
public void DoSomething(Vehicle vehicle) =>
this.EnsureThreadSafe(ref dispatch)
.Via(nameof(DoSomething), vehicle, () => throw new NotImplementedException());
// boilerplate end
public void Run(Vehicle vehicle) =>
DoSomething(vehicle);
public void DoSomething(Car car) =>
Console.WriteLine("Doing something with a car...");
public void DoSomething(Bike bike) =>
Console.WriteLine("Doing something with a bike...");
}
public abstract class Vehicle { }
public class Car : Vehicle { }
public class Bike : Vehicle { }
class MainClass {
public static void Main (string[] args) {
var manager = new VehicleManager();
manager.Run(new Car());
manager.Run(new Bike());
Console.WriteLine("Done.");
}
}
On repl.it :
https://repl.it/#ysharp_design/SO48975551
See also this related pull request (for the unit tests) :
https://github.com/waf/MultipleDispatchBenchmarks/pull/1/files
'HTH
Sorry for the bad title, finding it hard to narrow down what exactly this problem relates to.
I have two class hierarchies that are essentially built in parallel: for every subtype of BaseObject, there's a subtype of BaseUIObject. The specific reason for this is because BaseObjects are actually Scriptable Objects (unity), and so I'm using another set of classes to represent each instance of one of those scriptable objects.
Example code:
public abstract class BaseUIObject {
public BaseObject someObject;
public void Setup(BaseObject baseObject)
{ this.baseObject = baseObject; }
}
public class SomeUIObject : BaseUIObject {
public void Setup(SomeObject someObject)
{ base.Setup(someObject); SomeUIObjectSpecificRoutine(); }
private void SomeObjectSpecificRoutine() {
someObject.doSubClassFunction();
}
}
When passing the object of type SomeObject to the Setup of SomeUIObject, it becomes stored as a BaseObject instead of SomeObject. Is there any clean way to prevent this happening?
Right now the two options I have are either to define the someObject variable in every subclass of BaseUIObject, or to explicitly cast (SomeObject)someObject every time I use it in SomeUIObject's methods. Neither of these methods seem clean and I feel like there must be some nicer way of using inheritance to do this.
Thanks for any help.
Seems like a good place for Generics to me:
public abstract class BaseUIObject<T> where T : BaseObject
{
public T theObject { get; private set; }
public virtual void Setup(T baseObject)
{
this.theObject = baseObject;
}
}
And then, in your concrete UI objects:
public class SomeUIObject : BaseUIObject<SomeObject>
{
public override void Setup(SomeObject someObject)
{
base.Setup(someObject);
SomeUIObjectSpecificRoutine();
}
// rest of concrete class code...
}
I hope I can explain this problem right, it's a bit confusing for me.
I have been working on a game library similar to flixel but, using C#'s XNA framework instead of Flash. Right now the current class layout is something like this.
ClxBasic -> ClxObject -> ClxSprite
Each class has a constructor and calls the constructor for the class below it. I use this code to do this.
namespace Test
{
public class ClxBasic
{
public ClxBasic()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
public class ClxObject : ClxBasic
{
public ClxObject() : base()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
public class ClxSprite : ClxObject
{
public ClxSprite() : base()
{
Constructor();
}
public void Constructor()
{
DoSomething();
}
}
}
So basically when I create a new ClxSprite it calls the ClxSprite constructor, then all the ones below it (ClxObject and ClxBasic).
I'm sure there is an easier way to do this and I am all ears.
However, my bigger issue is actually how to properly derive and override methods from the other classes.
The issue is that when creating a class that extends from ClxSprite, for example, when calling a method that was overridden from the most basic class (ClxBasic), it will only call the bottom method and not the top.
The reason I need to do this is because I have a global class which keeps control of all the objects derived from ClxBasic by adding themselves to a list in the ClxBasic constructor.
Here's some example code.
namespace Test
{
public static class ClxG()
{
public static List<ClxBasic> GlobalObjects; //All objects will be added here by the ClxBasic constructor
ClxSprite test = new ClxSprite();
GlobalObjects.Add(test);
public static Update()
{
foreach(ClxBasic basic in GlobalObjects)
basic.Update(); //Calling this calls ClxBasic.Update() when it should call ClxSprite.Update()
}
}
}
When calling basic.Update() it goes to the bottom Update, the one located in ClxBasic, despite the object being a ClxObject or ClxSprite or other derived class.
I have a limited fix as well, by changing the ClxBasic to ClxSprite in the foreach loop, you can call that classes constructor method properly. However, when making custom classes based off of the library who override a method, the lower Update is called.
However, the limit is that you can't add classes I didn't specifically plan for. For example, if I were to derive a class Player from ClxSprite and, override the Update() method, it would get added to the GlobalObjects list but, never have it's update called, the highest it will go is ClxSprite's.
The way I want it to work is, in Game1.cs I want to just be able to put FlxG.Update() in the Game.Update() loop and just be able to create the object and have my framework handle the rest.
I hope I've made a bit of sense, the whole thing feels like some sort of inheritance inception and kind of makes my brain hurt.
To also call a base class method as part of a child class implementation, you'd do this:
class Base {
public virtual void Method() {
// ...
}
}
class Derived : Base {
public override void Method() {
base.Method();
// ....
}
}
class Derived2 : Derived {
public override void Method() {
base.Method();
// ....
}
}
But the child method is not required to call the base one.
Constructors, on the other hand, are always required to (ultimately) call a base constructor.
Now, if you want a base class method to always be called as part of some processing, you can employ the template method pattern. Basically your base class has a non-virtual method that drives an algorithm that calls virtual (or abstract) methods; which the child classes can override to create their own versions.
You are properly using base() to call the constructors of your base classes. As for how you are defining your constructors, why is Constructor() a separate method, rather than the body of the different constructors? If you are only planning on calling Constructor() when you create a new insance of one of your classes, I would recommend moving Constructor() back into your actual constructors, like so:
namespace Test
{
public class ClxBasic
{
public ClxBasic()
{
// Do Something
}
}
public class ClxObject : ClxBasic
{
public ClxObject() : base()
{
// Do Something
}
}
public class ClxSprite : ClxObject
{
public ClxSprite() : base()
{
// Do Something
}
}
}
As for being able to call the appropriate Update() function, depending on the actual class of your object, you would accomplish this using the virtual and override keywords. You would use them like so:
namespace Test
{
public class ClxBasic
{
// Define the base function that can be overridden
// in subclasses.
public virtual void Update()
{
// Do Some Updates
}
}
public class ClxObject : ClxBasic
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
// Do Some Updates
}
}
public class ClxSprite : ClxObject
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
// Do Some Updates
}
}
}
When you call Update() on an object that is an instance of a class derived from ClxBasic, the top-level Update() function in that objects inheritance-chain will be called. For instance:
ClxBasic clxBasic = new ClxBasic(); // Calls ClxBasic.Update()
ClxBasic clxObject = new ClxObject(); // Calls ClxObject.Update()
ClxBasic clxSprite = new ClxSprite(); // Calls ClxSprite.Update()
In addition, if you want your Update() functions to call the Update() function of their parent, you can use the base keyword.
For example:
public class ClxSprite : ClxObject
{
// We're overridiung the base function, so we
// must mark this function as an override.
public override void Update()
{
base.Update(); // Will call ClxObject's Update() function
// Do Some Updates
}
}
Based on your description, your goal seems to be to achieve polymorphic behavior among different game classes. A better solution is to define an interface that different game classes must implement. Then you can put all of your game objects in one generic container, such as an array list, and then have the master game loop iterate through the object list and invoke each object's update method the method during each overall update. I would design the classes like this:
interface IUpdatable {
void doUpdate();
}
class GameClassA : IUpdatable {
void doUpdate() { // }
}
class GameClassB : IUpdatable {
void doUpdate() { // }
}
etc.
Your goal is to achieve polymorphic behavior among objects of different classes but not necessarily to share data and common functionality. While you can achieve polymorphism through inheritance as well, it is better achieved in this case through simple interfaces and composition.
I have a abstract class named Vehicle:
public abstract class Vehicle {
public void run() {
addToRunningVehicleList();
}
}
I want that every classes that extends Vehicle must call super.run() if they override run method. For example:
public class Car {
#Override
public void run() { // Error here because does not call super.run()
carRunningAnimation();
}
}
Is it possible in OOP concept, or Java/C#?
EDIT: Following Petar Ivanov, I have this code:
public abstract class Vehicle {
public final void run() {
Log.e("Run", "Add To List");
runImp();
}
public void runImp() {}
}
public class Car extends Vehicle {
#Override
public void runImp() {
Log.e("Run", "Run in Car");
}
}
However, it's not very good for public APIs. When extending Vehicle, the end-users must override runImp, but then they have to call run() method, so I have to make public both run and runImp, which make nothing better.
Here is how I would do it (C#):
public abstract class Vehicle {
public void Run() {
//code that will always run
addToRunningVehicleList();
//code that can be overriden
RunImpl();
}
protected virtual void RunImpl() { }
}
public class Car : Vehicle {
protected override void RunImpl() {
carRunningAnimation();
}
}
You can make the RunImpl protected to make sure it can't be called outside the subclasses of Vehicle.
If you need to require certain code to run in addition to the child class' implementation, perhaps you need to split this into multiple methods:
(C# example)
public abstract class Vehicle
{
public void Run()
{
// Code that always runs before...
RunCore();
// Code that always runs after...
}
protected virtual void RunCore()
{
}
}
Remember who you are designing for. If it's an internal piece of code a comment will suffice. If it's a public API and you want people to inherit then you need to write a piece of documentation telling them to do it.
In C# you can do some sneaky stuff with virtual and non-virtual methods but in Java as all inheritence is virtual it's a lot harder to enforce this without using an abstract base class.
Using an ABT may limit your ability to provide further inheritence and force modification of other code.