I am trying to solve a simple OOPs problem. When I have to create few weapons and each weapon has a primary action and that primary action can be performed by a mouse click. Example for a shotgun it is shooting and for Katana is swinging it. Below my classes are.
public interface IShootable
{
void TakeShot();
}
public interface ISwingable
{
void Swing ();
}
public class ShotGun : IShootable
{
public void TakeShot()
{
}
}
public class Kanata : ISwingable
{
public void Swing ()
{
}
}
Each weapon has implemented different interface for their primary actions. (I'm not sure that I can create an abstract class, from which I can inherit these concrete classes. It seems not substitutable for two different type of weapons.)
What I wanted to achieve is in runtime when user selects one of the weapons, the user gets the right action on mouse click. For shotgun it is TakeShot() and for Katana it is Swing().
What I have to do adopt that. Or I should restructure the classes in some other way.
Both classes can both implement a third interface - IWeapon, with an Attack/Use method:
public interface IWeapon {
void Attack();
}
public class ShotGun : IShootable
{
void IWeapon.Attack() {
TakeShot();
}
public void TakeShot()
{
}
}
public class Kanata : ISwingable
{
public void Swing ()
{
}
void IWeapon.Attack() {
Swing();
}
}
Note that I have explicitly implemented the IWeapon interface here. You don't have to do it explicitly, and can still do it the "normal way". but I prefer it this way. This way, when you have a Katana object, only Swing is visible, but not Attack. I just feel that having both methods visible is confusing.
Also note that IWeapon is unrelated to ISwingable and IShootable, because swingable things (tennis racket) and shootable things (water pistol) are not necessarily weapons.
You might want to do something more generic:
public interface IWeaponPrimaryAction
{
void PerformPrimaryAction();
}
public interface IWeaponAction
{
void PrimaryAction();
}
public class Shoot :IWeaponAction
{
public void PrimaryAction()
{
//Fire in the hole
}
}
public class Swing :IWeaponAction
{
public void PrimaryAction()
{
//Into pieces
}
}
public class ShotGun : IWeaponPrimaryAction
{
private IWeaponAction _action = new Shoot();
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
public class Kanata : IWeaponPrimaryAction
{
private IWeaponAction _action = new Swing();
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
Better than that just inject the action:
public class ShotGun : IWeaponPrimaryAction
{
private IWeaponAction _action;
public ShotGun(IWeaponAction action)
{
_action = action;
}
public void PerformPrimaryAction()
{
_action.PrimaryAction();
}
}
My preference would be what #Riki suggests and create an interface that all weapons inherit IWeapon with a single method IWeapon.PerformPrimaryAction(). However if you don't like that you could create a "base" interface that all weapon interfaces derive from, then at runtime use casting, is or as to determine which weapon you have:
public interface IWeapon {};
public interface IShootable : IWeapon
{
void TakeShot();
}
public interface ISwingable : IWeapon
{
void Swing ();
}
public partial class YourGameClass
{
public void DoTheAction (IWeapon weapon)
{
if (weapon is IShootable)
(weapon as IShootable).TakeShot();
if (weapon is ISwingable)
(weapon as ISwingable).Swing();
}
}
I'm trying to get my head around making a simplified way of making items, lists and databases in C# And while everything works, It involved me needing to cast the results out.
So far I have the following
namespace Game.Database
{
public abstract class DatabaseItem : ScriptableObject
{
}
public class DatabaseList : ScriptableObject
{
public List<DatabaseItem> items;
}
public class ShipClass : ScriptableObject
{
public string shipClassID;
new public string name;
}
public class Ship : DatabaseItem
{
public string shipID;
new public string name;
public ScriptableObject shipClass;
}
}
public class Database : MonoBehaviour
{
public List<DatabaseList> lists;
void Start()
{
Ship ship = (Ship)lists[0].items[0];
Debug.Log(shipClass.shipID);
ShipClass shipClass = (ShipClass)ship.shipClass;
Debug.Log(shipClass.shipClassID);
}
}
Bear in mind this is a unity project so these items are being instantiated and data being assigned through the UI.
As you can see I have an abstract for my items and will have multiple types of item, and multiple lists. I am trying to avoid having to make multiple class' for my lists, one for each type of item. So i have abstracted my items off DatabaseItem so that I can store a List of DatabaseItem in my DatabaseList. However this means when reading my data out i need to cast this back into a Ship class.
While this isn't bad for a simple implementation, in production these will be nested requiring multiple casts to get down to the required data.
Unfortunately I find myself lacking in the required c# vocabulary to really google the issue. Looking at the Microsoft User-defined conversion operators and their example just doesn't make sense if it's even what i want to achieve.
EDIT -
The issue if not accessing the data, as I can do that, it's having to break down every level of the data as in the end this will be very generic used for all game data and very nested, so having to cast every level out to be able to break it down is what I'm trying to avoid.
One way would be to expose a method on each type of item that does the writing out of the data, so the calling code doesn't need to know the low level details.
See below, on how to avoid doing any casting.
namespace Game.Database
{
public abstract class DatabaseItem : ScriptableObject
{
public abstract void WriteOut();
}
public class DatabaseList : ScriptableObject
{
public List<DatabaseItem> items;
}
public class Ship : DatabaseItem
{
public string shipID;
new public string name;
public override void WriteOut()
{
Debug.Log(shipID);
}
}
}
public class Database : MonoBehaviour
{
public List<DatabaseList> lists;
void Start()
{
lists[0].items[0].WriteOut();
}
}
This way you are allowing each item type to handle its own writing out. Id suggest thinking carefully about your API.
To be even more SOLID and clean, you could use dependency injection and inject the writing into the type, see below for another example.
This has the benefit of allowing multiple types to use the same writer code and you also keep your class following the single responsibility principle.
namespace Game.Database
{
public interface IWriter
{
void Write(string output);
}
public class ConsoleWriter: IWriter
{
public void Write(string output)
{
Debug.Log(output);
}
}
public abstract class DatabaseItem : ScriptableObject
{
public abstract void WriteOut();
}
public class DatabaseList : ScriptableObject
{
public List<DatabaseItem> items;
}
public class Ship : DatabaseItem
{
private IWriter _writer;
public Ship(IWriter writer)
{
_writer = writer;
}
public string shipID;
new public string name;
public override void WriteOut()
{
_writer.Write(shipID);
}
}
}
public class Database : MonoBehaviour
{
public List<DatabaseList> lists;
void Start()
{
lists[0].items[0].WriteOut();
}
}
Something like this should be a good starting point. The specific implementations need to be adapted to your game's needs. More informations about generic types here.
public abstract class Item: ScriptableObject
{
public string name;
public abstract void Use();
}
public class Ship: Item
{
public string id;
public override void Use()
{
Debug.Log($"I'm a Ship, my name is {name}, my id is {id}.");
}
}
public class Plane: Item
{
public float speed;
public override void Use()
{
Debug.Log($"I'm a Plane, my name is {name}, my speed is {speed}.");
}
}
public class Database: ScriptableObject
{
[SerializeField] private List<Item> items;
public T GetItem<T>(int i) { return (T) items[i]; }
public Item AddItem() { ... }
public Item RemoveItem() { ... }
}
public class DatabaseHolder: MonoBehaviour
{
public Database database;
void Start()
{
Ship ship = database.GetItem<Ship>(0);
// Or...
Plane plane = database.GetItem<Plane>(1);
}
}
I hope my question is legit because i'm not really used to all the hierarchical class structs.
I try to encapsulate a class that delivers the same functions for two different cameras connected to device. Those functions are thought to be within the class DeviceObject whilst I want to access those functions by using an instance of Camera1 or Camera2. Here's some pseudo code that might not work:
public class Camera1 : DeviceObject
{
public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM1;
}
public class Camera2 : DeviceObject
{
public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM2;
}
public class DeviceObject
{
public void SomeFunction()
{
HardwareDriver.Function(SelectedCamera);
}
}
What I want is to easly access the methods of DeviceObject dependend on the Camera-Class:
public void Method()
{
Camera1 Cam1 = New Camera1();
Camera2 Cam2 = New Camera2();
Cam1.SomeFunction();
Cam2.SomeFunction();
}
I apologize if this is a stupid question but after 7 hours of programming I'm completely stuck and don't get it in my head anymore :)
UPDATE:
I have implemented - as entirely all of you have recommended - an abstract base class and derivate the Camera Objects as member of the base class.
What I didn't know so far, that it's possible to cast derived classes to the type of base classes. That was absolutely new to me but helped me a looot! with my implementation.
So thanks to all of you who helped me without minusing me to hell :)
Why not use an abstract class?
public class Camera1 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
public abstract Generic.CameraSelect CameraType { get; set; }
public void SomeFunction()
{
HardwareDriver.Function(this);
}
}
You typically only use inheritance when you need different implementation (methods). If the implementation is the same for both cameras but the data involved is different, you can use one class and a factory to "create" a camera with the appropriate settings.
public class CameraFactory
{
public static Camera1 {
get {
return new Camera {Camera = Generic.CameraSelect.CAM1};
}
public static Camera2 {
get {
return new Camera {Camera = Generic.CameraSelect.CAM2};
}
}
That's not the only way to do it, but it is one way.
Also note that if the Camera property should not change then make it get-only (or at worst use a private setter.
As other people have suggested, the answer to your question is probably to add an abstract / override:
public class Camera1 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
public abstract Generic.CameraSelect CameraType { get; set; }
public void SomeFunction()
{
HardwareDriver.Function(this);
}
}
However, I was triggered by the HardwareDriver class. There are two points I'd like to make here:
Drivers work on capabilities, not on names. If you're goal is decomposition, you might want to go for a double dispatch that calls stuff depending on the scope.
What's the purpose of a camera and why is it modelled the way 'the world' works?
Double dispatch
Let's start with the double dispatch. The way I see it, you'll probably end up with a large 'switch' block somewhere that incorporates the logic. That doens't make a lot of sense to me. Basically you probably attempt to decouple the objects from the logic -- so let's use inheritance to do that. In this case, it'll work like this:
public class Camera1 : Camera
{
public override void SomeFunction(IDeviceVisitor driver)
{
// Very simple camera:
driver.HandleAngle(this, 12.0);
driver.GenerateModel();
}
}
public class Camera2 : Camera
{
public override void SomeFunction(IDeviceVisitor driver)
{
// This camera understands focus
driver.HandleAngle(this, 12.0);
driver.HandleFocus(this, focus, this.focus * 1.2);
driver.GenerateModel();
}
}
public class SomeHardwareDriver : IDeviceVisitor { ... }
public interface IDeviceVisitor
{
void HandleFocus(Camera camera, double focusValue, double realDistance);
void HandleAngle(Camera camera, double angle);
void GenerateModel();
// [...]
// etc
}
public abstract class Camera
{
public abstract void SomeFunction(IDeviceVisitor driver);
}
The reason I pass this along is because you might want to call another camera function from within the HardwareDriver to do the magic.
Modelling in the way the world works
If two camera have nothing with each other in common, don't give them a common base class. It makes no sense.
Or the more general rule: always remember that a class model doesn't need to make sense to you as a person; it has to make sense to a computer.
How to know when you're running the wrong way
2 clues:
If you end up with large switch blocks, a lot of if-then-else's, etc -- then you're probably doing it wrong.
If you copy-paste code, you're probably doing it wrong.
You can have a encapsulating method which accepts a parameter of DeviceObject like
public void CallSomeFunction(DeviceObject dobj)
{
dobj.SomeFunction();
}
Then you can create an instance of any of camera base type and call the method
Camera1 Cam1 = New Camera1();
CallSomeFunction(cam1);
I'm trying to design a few classes for a game, but I'm not sure I'm doing it right.
I have two classes: Actor and Building.
These have a few subclasses: Policeman, Fireman and PoliceStation, FireStation.
I want to be able to put all these items together in a list to iterate through later, so I've added a base class: GameEntity.
So what I have is this:
public abstract class GameEntity:
{
public GameEntity()
{
}
}
public class Actor: GameEntity
{
public int _speed;
public TileSprite _UI;
public Actor()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoActing()
{
}
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
}
public class Building: GameEntity
{
public TileSprite _UI;
public Building()
{
}
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public virtual void OnClick()
{
//Do stuff here
}
public void DoBuilding()
{
}
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
}
Now, I want to be able to do this:
List<GameEntity> Entities = new List<GameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation
Entities.Add(a1);
Entities.Add(b1);
foreach(GameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
//If Actor then do
ent.DoActing();
//If Building then do
ent.DoBuilding();
}
}
Now, in order to do the last bit, would it be best if I implement an interface that contains the OnClick and CollidesWith, or can I do it with inheritance?
If so, how would I do this?
Cheers.
This is only to give you the idea, I guess that's what you need.
public interface IGameEntity
{
bool CollidesWith();
void OnClick();
void DoActing();
}
public class Actor : IGameEntity { //Interface implemented }
public class Building: IGameEntity { //Interface implemented }
public class Policeman: IGameEntity { //Interface implemented }
public class Fireman: IGameEntity { //Interface implemented }
public class FireStation: IGameEntity { //Interface implemented }
In your client object just do something like this:
List<IGameEntity> entities = new List<IGameEntity>()
{
new Actor(),
new Building(),
new Policeman(),
new Fireman(),
new Fireman()
};
foreach (IGameEntity entity in entities)
{
entity.CollidesWith();
entity.OnClick();
entity.DoActing();
}
Number of ways to go here.
If all GameEntities can be clicked on then you could add an OnClick event property to the base class.
If Not then I'd have an Interface IClick and then implement that on clickable entities.
Collision, depends.
Building don't move about so they can't collide with anything, but they can be collided with and so for instance you might want do a damage rountine, which then suggests a destroyed, routine a repair routine maybe.
There's no right answer, but
Three code smells would be a
A Base class with nothing in it.
A very deep inheritance hierarchy (more than two levels is cause for suspicion in my book)
So if you start seeing GameEntity -> BuildingEntity -> ActiveBuildingEntity -> RepairableBuildingEntity, you are in a mess that's about to get messier.
And above all a base class with do nothing methods in it that only exist because you need to add behaviour (override) in some descendants.
Don't be scared about having a few interfaces. IClick, ICollision, IDamage, IRepair etc. It's way better than implying a building can crash into a car.
You could do something like this:
public interface IGameEntity
{
void OnClick();
bool CollidesWith(Vector2 pos);
void Do();
}
public abstract class Actor: IGameEntity
{
public int _speed;
public TileSprite _UI;
public virtual bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void OnClick();
// can be marked virtual with implementation if you want a default
// this way base classes will be forced to implement their own implementation
public abstract void Do();
}
public class Policeman: Actor
{
public Policeman()
{
_speed = 10;
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
//Do Acting for Police
}
}
public abstract class Building: IGameEntity
{
public TileSprite _UI;
public bool CollidesWith(Vector2 pos)
{
//Do stuff here
}
public abstract void OnClick();
public abstract void Do();
}
public class PoliceStation: Building
{
public PoliceStation()
{
}
public override void OnClick()
{
//Do stuff
}
public override void Do()
{
// Do Building
}
}
If Game Entity is just an interface then there is no need to make it an abstract class. If Actor and Building can never exist as a stand alone object then they should be abstract. If DoActing, DoBuilding, and OnClick must be overridden by the base classes then you can mark them abstract in actor and Building.
I followed norlesh's suggestion to just have one method Do. You could also make Actor and Building have their own abstract methods and IGameEntity would not have Do. Then you would put an if statement and check the if each object is of type builder then they would run the build and if of type actor then run act.
I think the way of having one method is better, since you eliminate one step. From a design perspective I'm not sure but it feels the same to me either way.
List<IGameEntity> Entities = new List<IGameEntity>();
Actor a1 = new PoliceMan();
Building b1 = new PoliceStation();
Entities.Add(a1);
Entities.Add(b1);
foreach(IGameEntity ent in Entities)
{
if (ent.CollidesWith(something))
{
ent.OnClick();
ent.Do();
}
}
Adding a virtual doStuff() to GameEntity and overriding it in the child classes instead of having unique method names like DoActing and DoBuilding then calling that from your loop should do what you want.
It's weird that this is the first time I've bumped into this problem, but:
How do you define a constructor in a C# interface?
Edit
Some people wanted an example (it's a free time project, so yes, it's a game)
IDrawable
+Update
+Draw
To be able to Update (check for edge of screen etc) and draw itself it will always need a GraphicsDeviceManager. So I want to make sure the object has a reference to it. This would belong in the constructor.
Now that I wrote this down I think what I'm implementing here is IObservable and the GraphicsDeviceManager should take the IDrawable...
It seems either I don't get the XNA framework, or the framework is not thought out very well.
Edit
There seems to be some confusion about my definition of constructor in the context of an interface. An interface can indeed not be instantiated so doesn't need a constructor. What I wanted to define was a signature to a constructor. Exactly like an interface can define a signature of a certain method, the interface could define the signature of a constructor.
You can't. It's occasionally a pain, but you wouldn't be able to call it using normal techniques anyway.
In a blog post I've suggested static interfaces which would only be usable in generic type constraints - but could be really handy, IMO.
One point about if you could define a constructor within an interface, you'd have trouble deriving classes:
public class Foo : IParameterlessConstructor
{
public Foo() // As per the interface
{
}
}
public class Bar : Foo
{
// Yikes! We now don't have a parameterless constructor...
public Bar(int x)
{
}
}
As already well noted, you can't have constructors on an Interface. But since this is such a highly ranked result in Google some 7 years later, I thought I would chip in here - specifically to show how you could use an abstract base class in tandem with your existing Interface and maybe cut down on the amount of refactoring needed in the future for similar situations. This concept has already been hinted at in some of the comments but I thought it would be worth showing how to actually do it.
So you have your main interface that looks like this so far:
public interface IDrawable
{
void Update();
void Draw();
}
Now create an abstract class with the constructor you want to enforce. Actually, since it's now available since the time you wrote your original question, we can get a little fancy here and use generics in this situation so that we can adapt this to other interfaces that might need the same functionality but have different constructor requirements:
public abstract class MustInitialize<T>
{
public MustInitialize(T parameters)
{
}
}
Now you'll need to create a new class that inherits from both the IDrawable interface and the MustInitialize abstract class:
public class Drawable : MustInitialize<GraphicsDeviceManager>, IDrawable
{
GraphicsDeviceManager _graphicsDeviceManager;
public Drawable(GraphicsDeviceManager graphicsDeviceManager)
: base (graphicsDeviceManager)
{
_graphicsDeviceManager = graphicsDeviceManager;
}
public void Update()
{
//use _graphicsDeviceManager here to do whatever
}
public void Draw()
{
//use _graphicsDeviceManager here to do whatever
}
}
Then just create an instance of Drawable and you're good to go:
IDrawable drawableService = new Drawable(myGraphicsDeviceManager);
The cool thing here is that the new Drawable class we created still behaves just like what we would expect from an IDrawable.
If you need to pass more than one parameter to the MustInitialize constructor, you can create a class that defines properties for all of the fields you'll need to pass in.
A very late contribution demonstrating another problem with interfaced constructors. (I choose this question because it has the clearest articulation of the problem). Suppose we could have:
interface IPerson
{
IPerson(string name);
}
interface ICustomer
{
ICustomer(DateTime registrationDate);
}
class Person : IPerson, ICustomer
{
Person(string name) { }
Person(DateTime registrationDate) { }
}
Where by convention the implementation of the "interface constructor" is replaced by the type name.
Now make an instance:
ICustomer a = new Person("Ernie");
Would we say that the contract ICustomer is obeyed?
And what about this:
interface ICustomer
{
ICustomer(string address);
}
You can't.
Interfaces define contracts that other objects implement and therefore have no state that needs to be initialized.
If you have some state that needs to be initialized, you should consider using an abstract base class instead.
I was looking back at this question and I thought to myself, maybe we are aproaching this problem the wrong way. Interfaces might not be the way to go when it concerns defining a constructor with certain parameters... but an (abstract) base class is.
If you create a base class with a constructor on there that accepts the parameters you need, every class that derrives from it needs to supply them.
public abstract class Foo
{
protected Foo(SomeParameter x)
{
this.X = x;
}
public SomeParameter X { get; private set }
}
public class Bar : Foo // Bar inherits from Foo
{
public Bar()
: base(new SomeParameter("etc...")) // Bar will need to supply the constructor param
{
}
}
It is not possible to create an interface that defines constructors, but it is possible to define an interface that forces a type to have a paramerterless constructor, though be it a very ugly syntax that uses generics... I am actually not so sure that it is really a good coding pattern.
public interface IFoo<T> where T : new()
{
void SomeMethod();
}
public class Foo : IFoo<Foo>
{
// This will not compile
public Foo(int x)
{
}
#region ITest<Test> Members
public void SomeMethod()
{
throw new NotImplementedException();
}
#endregion
}
On the other hand, if you want to test if a type has a paramerterless constructor, you can do that using reflection:
public static class TypeHelper
{
public static bool HasParameterlessConstructor(Object o)
{
return HasParameterlessConstructor(o.GetType());
}
public static bool HasParameterlessConstructor(Type t)
{
// Usage: HasParameterlessConstructor(typeof(SomeType))
return t.GetConstructor(new Type[0]) != null;
}
}
Hope this helps.
One way to solve this problem i found is to seperate out the construction into a seperate factory. For example I have an abstract class called IQueueItem, and I need a way to translate that object to and from another object (CloudQueueMessage). So on the interface IQueueItem i have -
public interface IQueueItem
{
CloudQueueMessage ToMessage();
}
Now, I also need a way for my actual queue class to translate a CloudQueueMessage back to a IQueueItem - ie the need for a static construction like IQueueItem objMessage = ItemType.FromMessage. Instead I defined another interface IQueueFactory -
public interface IQueueItemFactory<T> where T : IQueueItem
{
T FromMessage(CloudQueueMessage objMessage);
}
Now I can finally write my generic queue class without the new() constraint which in my case was the main issue.
public class AzureQueue<T> where T : IQueueItem
{
private IQueueItemFactory<T> _objFactory;
public AzureQueue(IQueueItemFactory<T> objItemFactory)
{
_objFactory = objItemFactory;
}
public T GetNextItem(TimeSpan tsLease)
{
CloudQueueMessage objQueueMessage = _objQueue.GetMessage(tsLease);
T objItem = _objFactory.FromMessage(objQueueMessage);
return objItem;
}
}
now I can create an instance that satisfies the criteria for me
AzureQueue<Job> objJobQueue = new JobQueue(new JobItemFactory())
hopefully this helps someone else out someday, obviously a lot of internal code removed to try to show the problem and solution
One way to solve this problem is to leverage generics and the new() constraint.
Instead of expressing your constructor as a method/function, you can express it as a factory class/interface. If you specify the new() generic constraint on every call site that needs to create an object of your class, you will be able to pass constructor arguments accordingly.
For your IDrawable example:
public interface IDrawable
{
void Update();
void Draw();
}
public interface IDrawableConstructor<T> where T : IDrawable
{
T Construct(GraphicsDeviceManager manager);
}
public class Triangle : IDrawable
{
public GraphicsDeviceManager Manager { get; set; }
public void Draw() { ... }
public void Update() { ... }
public Triangle(GraphicsDeviceManager manager)
{
Manager = manager;
}
}
public TriangleConstructor : IDrawableConstructor<Triangle>
{
public Triangle Construct(GraphicsDeviceManager manager)
{
return new Triangle(manager);
}
}
Now when you use it:
public void SomeMethod<TBuilder>(GraphicsDeviceManager manager)
where TBuilder: IDrawableConstructor<Triangle>, new()
{
// If we need to create a triangle
Triangle triangle = new TBuilder().Construct(manager);
// Do whatever with triangle
}
You can even concentrate all creation methods in a single class using explicit interface implementation:
public DrawableConstructor : IDrawableConstructor<Triangle>,
IDrawableConstructor<Square>,
IDrawableConstructor<Circle>
{
Triangle IDrawableConstructor<Triangle>.Construct(GraphicsDeviceManager manager)
{
return new Triangle(manager);
}
Square IDrawableConstructor<Square>.Construct(GraphicsDeviceManager manager)
{
return new Square(manager);
}
Circle IDrawableConstructor<Circle>.Construct(GraphicsDeviceManager manager)
{
return new Circle(manager);
}
}
To use it:
public void SomeMethod<TBuilder, TShape>(GraphicsDeviceManager manager)
where TBuilder: IDrawableConstructor<TShape>, new()
{
// If we need to create an arbitrary shape
TShape shape = new TBuilder().Construct(manager);
// Do whatever with the shape
}
Another way is by using lambda expressions as initializers. At some point early in the call hierarchy, you will know which objects you will need to instantiate (i.e. when you are creating or getting a reference to your GraphicsDeviceManager object). As soon as you have it, pass the lambda
() => new Triangle(manager)
to subsequent methods so they will know how to create a Triangle from then on. If you can't determine all possible methods that you will need, you can always create a dictionary of types that implement IDrawable using reflection and register the lambda expression shown above in a dictionary that you can either store in a shared location or pass along to further function calls.
The generic factory approach still seems ideal. You would know that the factory requires a parameter, and it would just so happen that those parameters are passed along to the constructor of the object being instantiated.
Note, this is just syntax verified pseudo code, there may be a run-time caveat I'm missing here:
public interface IDrawableFactory
{
TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager)
where TDrawable: class, IDrawable, new();
}
public class DrawableFactory : IDrawableFactory
{
public TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager)
where TDrawable : class, IDrawable, new()
{
return (TDrawable) Activator
.CreateInstance(typeof(TDrawable),
graphicsDeviceManager);
}
}
public class Draw : IDrawable
{
//stub
}
public class Update : IDrawable {
private readonly GraphicsDeviceManager _graphicsDeviceManager;
public Update() { throw new NotImplementedException(); }
public Update(GraphicsDeviceManager graphicsDeviceManager)
{
_graphicsDeviceManager = graphicsDeviceManager;
}
}
public interface IDrawable
{
//stub
}
public class GraphicsDeviceManager
{
//stub
}
An example of possible usage:
public void DoSomething()
{
var myUpdateObject = GetDrawingObject<Update>(new GraphicsDeviceManager());
var myDrawObject = GetDrawingObject<Draw>(null);
}
Granted, you'd only want the create instances via the factory to guarantee you always have an appropriately initialized object. Perhaps using a dependency injection framework like AutoFac would make sense; Update() could "ask" the IoC container for a new GraphicsDeviceManager object.
You could do this with generics trick, but it still is vulnerable to what Jon Skeet wrote:
public interface IHasDefaultConstructor<T> where T : IHasDefaultConstructor<T>, new()
{
}
Class that implements this interface must have parameterless constructor:
public class A : IHasDefaultConstructor<A> //Notice A as generic parameter
{
public A(int a) { } //compile time error
}
The purpose of an interface is to enforce a certain object signature. It should explicitly not be concerned with how an object works internally. Therefore, a constructor in an interface does not really make sense from a conceptual point of view.
There are some alternatives though:
Create an abstract class that acts as a minimal default implementation.
That class should have the constructors you expect implementing classes
to have.
If you don't mind the overkill, use the AbstractFactory pattern and
declare a method in the factory class interface that has the required
signatures.
Pass the GraphicsDeviceManager as a parameter to the Update and Draw methods.
Use a Compositional Object Oriented Programming framework to pass the GraphicsDeviceManager into the part of the object that requires it. This is a pretty experimental solution in my opinion.
The situation you describe is not easy to handle in general. A similar case would be entities in a business application that require access to the database.
you don't.
the constructor is part of the class that can implement an interface. The interface is just a contract of methods the class must implement.
It would be very useful if it were possible to define constructors in interfaces.
Given that an interface is a contract that must be used in the specified way. The following approach might be a viable alternative for some scenarios:
public interface IFoo {
/// <summary>
/// Initialize foo.
/// </summary>
/// <remarks>
/// Classes that implement this interface must invoke this method from
/// each of their constructors.
/// </remarks>
/// <exception cref="InvalidOperationException">
/// Thrown when instance has already been initialized.
/// </exception>
void Initialize(int a);
}
public class ConcreteFoo : IFoo {
private bool _init = false;
public int b;
// Obviously in this case a default value could be used for the
// constructor argument; using overloads for purpose of example
public ConcreteFoo() {
Initialize(42);
}
public ConcreteFoo(int a) {
Initialize(a);
}
public void Initialize(int a) {
if (_init)
throw new InvalidOperationException();
_init = true;
b = a;
}
}
One way to force some sort of constructor is to declare only Getters in interface, which could then mean that the implementing class must have a method, ideally a constructor, to have the value set (privately) for it.
While you can't define a constructor signature in an interface, I feel it's worth mentioning that this may be a spot to consider an abstract class. Abstract classes can define unimplemented (abstract) method signatures in the same way as an interface, but can also have implemented (concrete) methods and constructors.
The downside is that, because it is a type of class, it cannot be used for any of the multiple inheritance type scenarios that an interface can.
I use the following pattern to make it bulletproof.
A developer who derives his class from the base can't accidentally create a public accessible constructor
The final class developer are forced to go through the common create method
Everything is type-safe, no castings are required
It's 100% flexible and can be reused everywhere, where you can define your own base
class.
Try it out you can't break it without making modifications to the base classes (except
if you define an obsolete flag without error flag set to true, but even then you end up with a warning)
public abstract class Base<TSelf, TParameter>
where TSelf : Base<TSelf, TParameter>, new()
{
protected const string FactoryMessage = "Use YourClass.Create(...) instead";
public static TSelf Create(TParameter parameter)
{
var me = new TSelf();
me.Initialize(parameter);
return me;
}
[Obsolete(FactoryMessage, true)]
protected Base()
{
}
protected virtual void Initialize(TParameter parameter)
{
}
}
public abstract class BaseWithConfig<TSelf, TConfig>: Base<TSelf, TConfig>
where TSelf : BaseWithConfig<TSelf, TConfig>, new()
{
public TConfig Config { get; private set; }
[Obsolete(FactoryMessage, true)]
protected BaseWithConfig()
{
}
protected override void Initialize(TConfig parameter)
{
this.Config = parameter;
}
}
public class MyService : BaseWithConfig<MyService, (string UserName, string Password)>
{
[Obsolete(FactoryMessage, true)]
public MyService()
{
}
}
public class Person : Base<Person, (string FirstName, string LastName)>
{
[Obsolete(FactoryMessage,true)]
public Person()
{
}
protected override void Initialize((string FirstName, string LastName) parameter)
{
this.FirstName = parameter.FirstName;
this.LastName = parameter.LastName;
}
public string LastName { get; private set; }
public string FirstName { get; private set; }
}
[Test]
public void FactoryTest()
{
var notInitilaizedPerson = new Person(); // doesn't compile because of the obsolete attribute.
Person max = Person.Create(("Max", "Mustermann"));
Assert.AreEqual("Max",max.FirstName);
var service = MyService.Create(("MyUser", "MyPassword"));
Assert.AreEqual("MyUser", service.Config.UserName);
}
EDIT:
And here is an example based on your drawing example that even enforces interface abstraction
public abstract class BaseWithAbstraction<TSelf, TInterface, TParameter>
where TSelf : BaseWithAbstraction<TSelf, TInterface, TParameter>, TInterface, new()
{
[Obsolete(FactoryMessage, true)]
protected BaseWithAbstraction()
{
}
protected const string FactoryMessage = "Use YourClass.Create(...) instead";
public static TInterface Create(TParameter parameter)
{
var me = new TSelf();
me.Initialize(parameter);
return me;
}
protected virtual void Initialize(TParameter parameter)
{
}
}
public abstract class BaseWithParameter<TSelf, TInterface, TParameter> : BaseWithAbstraction<TSelf, TInterface, TParameter>
where TSelf : BaseWithParameter<TSelf, TInterface, TParameter>, TInterface, new()
{
protected TParameter Parameter { get; private set; }
[Obsolete(FactoryMessage, true)]
protected BaseWithParameter()
{
}
protected sealed override void Initialize(TParameter parameter)
{
this.Parameter = parameter;
this.OnAfterInitialize(parameter);
}
protected virtual void OnAfterInitialize(TParameter parameter)
{
}
}
public class GraphicsDeviceManager
{
}
public interface IDrawable
{
void Update();
void Draw();
}
internal abstract class Drawable<TSelf> : BaseWithParameter<TSelf, IDrawable, GraphicsDeviceManager>, IDrawable
where TSelf : Drawable<TSelf>, IDrawable, new()
{
[Obsolete(FactoryMessage, true)]
protected Drawable()
{
}
public abstract void Update();
public abstract void Draw();
}
internal class Rectangle : Drawable<Rectangle>
{
[Obsolete(FactoryMessage, true)]
public Rectangle()
{
}
public override void Update()
{
GraphicsDeviceManager manager = this.Parameter;
// TODo manager
}
public override void Draw()
{
GraphicsDeviceManager manager = this.Parameter;
// TODo manager
}
}
internal class Circle : Drawable<Circle>
{
[Obsolete(FactoryMessage, true)]
public Circle()
{
}
public override void Update()
{
GraphicsDeviceManager manager = this.Parameter;
// TODo manager
}
public override void Draw()
{
GraphicsDeviceManager manager = this.Parameter;
// TODo manager
}
}
[Test]
public void FactoryTest()
{
// doesn't compile because interface abstraction is enforced.
Rectangle rectangle = Rectangle.Create(new GraphicsDeviceManager());
// you get only the IDrawable returned.
IDrawable service = Circle.Create(new GraphicsDeviceManager());
}