Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Let's say I have the following inheritance tree:
______ Object______
/ \
Food Material
/ \ / \
Egg Carrot Box Axe
Expressed like this in C#
class Object { ... }
class Food : Object { ... }
class OfficeMaterial : Object{ ... }
class Box : OfficeMaterial { ... }
class Spoon : OfficeMaterial { ... }
class Egg : Food { ... }
class Carrot : Food { ... }
And now I want to share the functionality only between the class Box and Egg, for instance:
bool opened = true;
public void Open() { open = true; }
public void Close() { open = false; }
public bool IsOpen() { return opened; }
This is a short example, but it could be something much longer.
What would be the proper way to do it? If I use inheritance, other classes like Carrot and Axe will get it, which is something I do not wish.
UPDATE
Many people mention Composition. Could someone show me how that would work in the example I presented?
You have a few options:
Use interfaces
Ex:
public interface IOpenable
{
void Open();
void Close();
bool IsOpen();
}
Then any class that needs the openable/closable behavior can implement the interface accordingly.
Favor composition over inheritance and compose your objects out of other objects that implement the desired behavior.
Why not use an interface? IOpenable?
interface IOpenable {
void Open();
void Close();
bool IsOpen();
}
When I think about the similarities between Egg and Box that are not properties shared by Carrot and Axe I think first about the fact that they contain something.
Egg and Box have Contents which can be exposed, hidden, added, removed, etc.
Notice the language here - Egg and Box have Contents. The word have (or has) is an indicator that an object representing the Contents of another object should be used as a composition element.
An Egg is a type of Food. An Egg has Contents which are a Yolk and an EggWhite.
A Box is a type of OfficeMaterial. A Box has Contents which are OfficeSupplies.
I could write something like this:
public class Food : Object
{
public void Eat() { }
}
public class OfficeMaterial : Object { }
public class Contents : Object
{
bool _visible = false;
List<Object> _things = new List<Object>();
public int Count { get { return _things.Count; } }
public bool IsOpen { get { return _visible; } }
public void Expose()
{
_visible = true;
}
public void Hide()
{
_visible = false;
}
public void Add(object thing)
{
_things.Add(thing);
}
public bool Remove(object thing)
{
return _things.Remove(thing);
}
}
public class Box : OfficeMaterial
{
public Contents BoxContents = new Contents();
}
public class Egg : Food
{
public Contents EggContents = new Contents();
}
Which would further allow me to:
void PlaceEggsInBox(int numEggs, Box box)
{
box.BoxContents.Expose();
if (box.BoxContents.AreVisible)
{
int eggsInBox = box.BoxContents.Things.Count(thing => thing is Egg);
for (int i = 0; i < numEggs - eggsInBox; i++)
{
box.BoxContents.Add(new Egg());
}
}
}
And then I might like to
void EatAllEggsInBox(Box box)
{
box.BoxContents.Expose();
foreach (Egg egg in box.BoxContents.Things.Where(thing => thing is Egg))
{
box.BoxContents.Remove(egg);
egg.EggContents.Expose();
if (egg.EggContents.AreVisible) egg.Eat();
}
}
The Eat() method is a method of the Food class. The Expose() method is a method of the Contents class, not the Food class or the OfficeMaterials class, nor of the Egg nor Box classes.
That's effectively multiple inheritance, which C# doesn't support other than through interfaces.
An option is to create an interface without the Open method (otherwise you'll have to implement it, so this is only for typing purposes) then implement a static extension methods in a static class alongside your interface.
public Interface IOpenable { }
public static class IOpenableExtensions {
public static Open(this IOpenable obj){
// work on any concrete implementation of IOpenable
}
}
Usage:
var box = new Box; // Box implements IOpenable
var egg = new Egg; // Egg implements IOpenable
box.Open();
egg.Open();
This pattern may work well when the actual inheritance reflect a core structure or organization while the interfaces provide common "behaviors" shared by certain objects. A class may implement one or more of such interfaces.
C# 8 default interface implementation might make this pattern more common.
In practice, you often end up needing to cast your objects to the interface when working with functions that deal with your base classes.
public IEnumerable<Food> GetFoods(){ ... }
public void HandleFood() {
for(var food in GetFoods()) {
if(food is IOpenable openableFood){
openableFood.Open();
}
}
}
Finally, note that this is not true multiple inheritance as you cannot inherit/override the extension methods themselves through a hierarchy of interfaces. If you have IOpenableFood inherit IOpenable with both an Open() extension method, you can't call base() in the derived one, and you'll have to choose which extension method to use explicitly. Best to avoid this altogether.
var egg = new Egg(); // Egg inherits both IOpenable and IOpenableFood
egg.Open(); // Error: Ambiguous method
IOpenableFoodExtensions.Open(egg); // OK, call that method
IOpenableExtensions.Open(egg); // OK, call other method
Related
public class BaseClass
{
public virtual void Display()
{
Console.WriteLine("I am Base Class");
}
public void BaseClassMethod()
{
Console.WriteLine("I am Base Class Method");
}
}
public class DerivedClass : BaseClass
{
public override void Display()
{
Console.WriteLine("I am Derived Class");
}
public void DerivedClassMethod()
{
Console.WriteLine("I am Derived Class Method");
}
}
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
bc.Display();
bc.BaseClassMethod();
Console.WriteLine("--------------");
DerivedClass dc = new DerivedClass();
dc.Display();
dc.BaseClassMethod();
dc.DerivedClassMethod();
Console.WriteLine("--------------");
BaseClass bc2 = new DerivedClass();
bc2.Display();
bc2.BaseClassMethod();
//bc2.DerivedClass(); --> I can't reach b2.DerivedClass() method
Console.ReadLine();
}
}
Hi everyone. I am trying to clear my mind about Why and where would I want to create and use derived class object from base class reference. I know how virtual works. I know derived class is a base class and I can override virtual methods. I can reach non virtual methods in base class. But I want to know where could and why would I want to use this style of object creation. Like in my last part of the example code;
BaseClass bc2 = new DerivedClass();
I can't reach derived class methods so I cant use derived class methods. But it is still derived class because of the new DerivedClass. If I use normal DerivedClass d = new DerivedClass(); style, I can use both class methods. I just cant find any reason and situation I would want to use this style. I would be glad if anyone show me in which situation I have to use derived class object from base class reference so I can understand this style is exist in language. I want to know WHY, I am not asking why this isn't working or something like that. Just want to know situations. Thank you.
There are two main usages:
1) Collections of multiple types
Lets change your example a little bit
public class Shape
{
public virtual void Display()
{
Console.WriteLine("I am a Shape");
}
public void BaseClassMethod()
{
Console.WriteLine("I am Base Class Method");
}
}
public class Square : Shape
{
public override void Display()
{
Console.WriteLine("I am Square");
}
public void DerivedClassMethod()
{
Console.WriteLine("I am Derived Class Method");
}
}
public class Circle : Shape
{
public override void Display()
{
Console.WriteLine("I am Circle");
}
}
class Program
{
static void Main(string[] args)
{
List<Shape> shapes = new List<Shape();
shapes.Add(new Square());
shapes.Add(new Circle());
I have a list that can hold Circles, Squares, and generic Shapes all in a single collection.
2) Polymorphism
Continuing on from the previous code
foreach(Shape shape in shapes)
{
shape.Display();
}
we don't know what kind of Shape the variable shape is, however we do know that whatever kind it is it will have a Display() method we can call and it will show the correct information.
Polymorphism is useful when you need to call a function on something but you don't know the specific type that something will be because you are pulling a collection of base types like above, or you want to write a function that can take in any kind of Shape because the function does not need to know the specific kind to do it's work.
public static void LogDisplay(Shape shape)
{
Console.WriteLine("I am about to call shape.Display()");
shape.Display();
Console.WriteLine("I am just called shape.Display()");
}
My favorite example, because people can understand the use, is logging. Imagine I create a website. When I'm developing the site, I want to log to my file system, because it's easy to access. When I deploy the website, I want to log to the event log, because maybe I don't have direct access to the file system on that machine.
However, I only want to change where things are logged, I want the base class to structure how the actual text looks. So I have my base class that formats text:
public abstract class BaseLogger
{
public abstract void LogException(Exception ex);
public abstract void LogUserMessage(string userMessage);
protected string GetStringFromException(Exception ex)
{
//....
}
protected string GetStringFromUserMessage(string userMessage)
{
//....
}
}
Now I can have a class that logs to the File System:
public class FileLogger : BaseLogger
{
public FileLogger(string filename)
{
//initialize the file, etc
}
public override void LogException(Exception ex)
{
var string = GetStringFromException(ex);
File.WriteAllLines(...);
}
public override void LogException(Exception ex)
{
var string = GetStringFromUserMessage(ex);
File.WriteAllLines(...);
}
}
and my class that logs to the Event Log:
public class EventLogger : BaseLogger
{
public EventLogger()
{
//initialize the eventlog, etc
}
public override void LogException(Exception ex)
{
var string = GetStringFromException(ex);
EventLog.WriteEntry(...);
}
public override void LogException(Exception ex)
{
var string = GetStringFromUserMessage(ex);
EventLog.WriteEntry(...);
}
}
Now in my program, I only care that I have a BaseLogger when I inject one into my classes. The implementation details are irrelevant, I just know that I can LogException and LogUserMessage no matter what I'm using.
When I'm using the logger I benefit from not caring which derived class I use. That's the benefit of treating each derived class like a base class. I can swap them out without my program caring.
There are many reasons to do this, mostly to do with code re-usability and extensiblity, which in other words, to make a small change or enhancement easily without needing to rewrite a whole lot.
A real world example (which happens frequently) is the case where you have different customers using your software which may require you to support different databases (or even different table structures). So in order to do that, you can derive implementations from a common base class, and vary in the implementation details without affecting the rest of the program.
This also follows the design principle "Program
to an 'interface', not an 'implementation'" which is explained in the GoF design pattern book
public abstract class ProviderBase
{
public abstract Employee[] GetAllEmployees();
}
public class MySqlProvider:ProviderBase
{
public override Employee[] GetAllEmployees()
{
string select = "select * from employees";
//query from mysql ...
}
}
public class MsSqlProvider : ProviderBase
{
public override Employee[] GetAllEmployees()
{
string select = "select * from user u left join employee_record e on u.id=e.id";
//query from mysql ...
}
}
Then in the main program you may be able to change the type of database implementation by configuration or Dependency Injection
ProviderBase provider = null;
if(databaseType == "MySql")
{
provider = new MySqlProvider();
}
else if (databaseType == "MsSql")
{
provider = new MsSqlProvider();
}
var employees = provider.GetAllEmployees();
//do something
I believe a lot of the reasoning behind the availability of using derived classes has to do with minimizing repeated code.
To reference a real life example...
If I was to ask you to describe the attributes and abilities of a car, and then was to ask you to do the same for an electric car, you would find that much of the attributes and abilities are shared by both. So instead of having it be two completely separate classes, it would be more efficient to create the base class Car, and derive electricCar from that. Then you will only need to account for the specific differences of the electric car within the derived class, and all the shared attributes and abilities will carry over.
Hope this helps you understand the usefulness of base classes and derived classes. Very oversimplified but I feel it may help you grasp the concept!
The main reason to use a base class is reusability and polymorphism
So you could create the class depending on a condition:
BaseClass bc
if(case1)
bc = new DerivedClass1();
else
bc = new DerivedClass2();
In the following application you can use bc even if you don't know what kind of derived class it is at compile time. You can pass it e.g. to other functions and call the overridden methode:
bc.Display();
Derived class methods can only be used when you know what kind of derived class you actual have. Then you can do a conversion.
DerivedClass1 dc = bc as DerivedClass1;
dc.DerivedClassMethod()
I've been having trouble even defining what I am looking for.
I am writing an app to determine winners in a tournament. I would like my base class to be able to change it's inheritance based on how many people are playing, given that multiple inheritance is not an option, and probably wouldn't be a very good one the more i think on it.
I see something along the lines of
class Base
{
//Constructor receiving the quantity of players
public Base (int quantityOfPlayers)
{
//Changes Base inheritance dynamically based on QuantityOfPlayers
switch (quantityOfPlayers)
{
case 4: (Base : FourPlayers);
case 5: (Base : FivePlayers);
}
}
}
But of course i can't seem to find a means (if there is one) of dynamically changing the inheritance like that. Otherwise I'm stuck using more complicated means though each of the getter and setter functions are going to be essentially the same.
Very good solutions. let me add that I'm using a GUI not the console.
I have to think on this, the factory class is good, but it has convinced me I'm over thinking my approach.
There is a software design pattern called strategy pattern for this kind of situation.
Define an interface for the game strategy
public interface IGameStrategy
{
// Things that depend on the number of players, go here...
}
The right strategy gets injected into the game through constructor injection
public class Game
{
private IGameStrategy _strategy;
// Constructor injection
public Game(IGameStrategy strategy)
{
_strategy = strategy;
}
// Things common to all types of games go here...
}
Define a factory method like this:
private IGameStrategy CreateGameStrategy(int numberOfPlayers)
switch (numberOfPlayers)
{
case 4:
return FourPlayersStrategy();
case 5:
return FivePlayersStrategy();
default:
throw new ArgumentException("Invalid number of players");
}
}
Then create a game like this:
var game = new Game(CreateGameStrategy(numberOfPlayers));
Of course the strategy classes implement the interface. They can do so directly or they can inherit a common abstract base class implementing the interface.
The game logic is split into things common to all types of games implemented in the Game class and things specific to the number of players implemented in the strategy classes.
You could create a factory class that generates the proper class based on the number of players:
public class PlayerQtyFactory
{
//You can add any other args you might need as well
public BaseClass CreatePlayerQty(int numPlayers)
{
switch (numPlayers)
{
Case 2:
return new TwoPlayers();
Case 3:
return new ThreePlayers();
{
}
}
Without knowing more about what you are trying to do, it is hard to say if this is the best approach, but it is certainly A aproach.
For this particular situation I would use a factoryesque (or just plan factory) solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tester
{
//declare common functionality
public interface ISharedFunctionality
{
//put all shared functionality here
void SomeMethod();
void SomeOtherMethod();
void DifferentMethod();
string Name {get;set;}
}
public interface ISinglePlayerFunctionality : ISharedFunctionality
{
//put single player functionality here
void SomeOtherMethod();
void SomeMethod();
}
public interface IMultiplePlayerFunctionality : ISharedFunctionality
{
//put multiplayer functionality here
void DifferentMethod();
void SomeMethod();
}
public class ImplementationBase : ISharedFunctionality
{
//shared implementation here
public void SomeMethod()
{
//do stuff
Console.WriteLine("In Base");
}
public void SomeOtherMethod()
{
//one you don't want to inherit in multiplayer
Console.WriteLine("In Base");
}
public void DifferentMethod()
{
Console.WriteLine("In Base");
}
public string Name
{
get;
set;
}
}
public class MultiPlayerImplementation : ImplementationBase, IMultiplePlayerFunctionality
{
//multiplay impl
// you inherit some method but don't want to inherit
//SomeOtherMethod when cast to ISharedFunctionality
void ISharedFunctionality.SomeMethod()
{
//when cast to ISharedFunctionality this method will execute not inherited
Console.WriteLine("In MutilPlayImplementation");
}
}
public class SinglePlayerImplementation : ImplementationBase , ISinglePlayerFunctionality
{
//singleplay impl
void ISharedFunctionality.SomeOtherMethod()
{
Console.WriteLine("In SinglePlayerImplementation" );
}
}
public class Factory
{
//logic to decide impl here
public ISharedFunctionality Create(int numberOfPlayer)
{
if (numberOfPlayer == 1)
{
return new SinglePlayerImplementation();
}
else if(numberOfPlayer > 1)
{
return new MultiPlayerImplementation();
}
return null;
}
}
class Program
{
static void Main(string[] args)
{
var factory = new Factory();
var results = new[]{factory.Create(1) , factory.Create(2) };
int j=0;
foreach (var i in results)
{
///for single player will be base
///multiplaryer will be mutliplayer
i.SomeMethod();
//for single player will be single player
// for multiplayer will be base
i.SomeOtherMethod();
i.DifferentMethod();
i.Name = "Item-Number-" + j;
Console.WriteLine();
}
}
}
}
The benefit to this is two fold, you now no longer have ambiguity in terms of what method is being called, and you have a unified place to construct future implementations based off of similair contracts (i.e. three player behavior, different menu behavior, and it might be even less code if you want the exact same methods to just behave differently
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# - Is there a better alternative than this to ‘switch on type’?
Consider the classic:
class Widget { }
class RedWidget : Widget { }
class BlueWidget : Widget { }
For the most part, in my UI, I can treat all Widgets the same. However, there are minor differences, which I need to if or switch through.
Possible approaches:
Enum Indicator - set by constructor
enum WidgetVariety { Red, Blue }
class Widget {
public WidgetVariety Variety { get; protected set; }
}
class RedWidget : Widget {
public RedWidget() {
Variety = Red;
}
}
// Likewise for BlueWidget...
switch (mywidget.Variety) {
case WidgetVariety.Red:
// Red specific GUI stuff
case WidgetVariety.Blue:
// Blue specific GUI stuff
}
Use is
Widget w = ...;
if (w is RedWidget) {
(RedWidget)w ...
}
else if (w is BlueWidget) {
(BlueWidget)w ...
}
The reason I've resorted to this is 1) Most of the code is already somewhat written this way, but much uglier. 2) 90% of the code is identical - basically just one column in a GridView needs to be handled differently depending on the type.
Which would you recommend? (Or anyone have a better solution?)
Edit I know I'll probably be recommended to the Visitor Pattern, but that simply seems to complicated for sparse, minor differences in this case.
Edit 2
So one particular difference I was having a hard time sorting out is this column that is different between the two types. In one case, it retrieves a bool value, and assigns that to the grid cell. In the other case, it gets a string value.
I suppose in this case, it should be obvious that I could define:
public object virtual GetColumn4Data();
public override GetColumn4Data() { return m_boolval; }
public override GetColumn4Data() { return m_mystring; }
This felt wrong to me initially, due to the use of object. However, that is the type of the property that I am assigning to in the cell, so of course this makes sense!
Too long at the office today it seems...
There's another possibility. Use virtual dispatch:
class Widget
{
public virtual void GuiStuff() { }
}
class RedWidget : Widget
{
public override void GuiStuff()
{
//... red-specific GUI stuff
base.GuiStuff();
}
}
class BlueWidget : Widget
{
public override void GuiStuff()
{
//... blue-specific GUI stuff
base.GuiStuff();
}
}
Subtype polymorphism is the best solution, avoiding this kind of checks is one of the main reasons OO was created.
Widget might have a method DoSomething() (abstract probably) and then RedWidget and BlueWidget would override it.
Also see Martin Fowler's Replace Conditional with Polymorphism:
Seen: You have a conditional that chooses different behavior depending on the type of an object.
Refactor: Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.
For your question under Edit #2, you could use a generic class to make the type vary among subclasses, though it may or may not work for you depending on your design. It will probably lead to other tough design decisions.
Rough example:
internal abstract class BaseClass
{
protected object mValue; // could also be defined as a T in BaseClass<T>
public object GetColumn4Data { get { return mValue; } }
}
// this is a group of classes with varying type
internal abstract class BaseClass<T> : BaseClass
{
public T GetTypedColumn4Data
{
get { return (T)mValue; }
set { mValue = value; }
}
}
// these are not really necessary if you don't plan to extend them further
// in that case, you would mark BaseClass<T> sealed instead of abstract
internal sealed class BoolSubClass : BaseClass<bool>
{
// no override necessary so far
}
internal sealed class StringSubClass : BaseClass<string>
{
// no override necessary so far
}
Notice, however, that you can't really get a single reference type that will have a varying return type on some property or method. A BaseClass reference will at best return a general type (like object).
I am programming a game as an exercise and I've run into a design problem. My role playing game will have the typical classes like Fighter, Wizard, Theif, Cleric. How do I design my classes so that players can multi-class? For example, one player might start off as a Fighter (and gain the related skills fighters have), then multi-class to a Wizard (at that point they gain wizard spells), and later on multi-class yet again to a rogue (now gaining all abilities rogues have). So this player is now a Fighter-Wizard-Rogue. I don't know to represent this in C#.
At first I tried to use the decorator pattern but I'm unable to multi-class multiple times with this. Any pointers on how to design this?
Only thing I can think of is having an IList<CharacterBaseClass> property for each character and adding Fighter, Wizard, Rogue, etc to this as the player multi-classes. So something like this..
class CharacterBaseClass
{
public IList<CharacterBaseClass> MultiClasses { get; set; }
// constructors, etc
}
and each time they mutli-class I add to the IList
// player starts off as Fighter
Warrior player1 = new Warrior();
// now multi-class to Wizard
player1.MultiClasses.Add(new Wizard());
// now multi-class to Theif
player1.MultiClasses.Add(new Theif());
I'm sure there must be a better way than this?
Just because your characters are wizards and warriors, that doesn't mean you have to create subclasses for them. Instead, ask yourself, "At the code level, what does a character's class do?" Likely, you won't want to have C# subclasses for character classes at all. Instead, figure out what the class actually does, and then determine the right way to model that in code.
For example, if character class restricts the equiment a character can use, then you can define a class for AllowedEquipment:
public class AllowedEquipment
{
public static AllowedEquiment Warrior()
{
return new AllowedEquipment() {
Daggers = true;
Swords = true;
Shields = true;
Armor = true
};
}
public static AllowedEquiment Wizard()
{
return new AllowedEquipment() {
Daggers = true;
Swords = false;
Shields = false;
Armor = true
};
}
public bool Daggers { get; set; }
public bool Swords { get; set; }
public bool Shields { get; set; }
public bool Armor { get; set; }
}
Don't feel you need to use subclasses to model every "is-a" relationship in your game.
Another option is to use the Type Object pattern to model your character classes. If you do that, it'd be easy to give each character a set of those Type Object instances instead of a single one, giving you, in effect, multiple inheritance.
With the decorator pattern, you could possibly do it.
Character person = new Character("Rambo");
person = new Fighter(person); // decorate him with Fighter skills
person = new Thief(person); // also decorate him with Thief skills
Personally I would probably look at attaching classes to the character instead:
Character person = new Character("Rambo");
person.AttachClass(new Fighter());
person.AttachClass(new Thief());
Of course, if you need complex interactions between the classes, so that not only does a Fighter/Thief gets bonuses and skills from each, but he gets something more as well, perhaps the only correct route for that might be to create specific multi-classes for all the combinations:
Character person = new Character("Rambo");
person.AttachClass(new FighterThief());
This would of course just explode with all the combinations.
What about a pure table-driven effort?
Place all applicable skills, spells, bonuses, effects, etc. in a hunking big table, then define the classes by linking a specific class to the specific items in that table. This way it would be much simpler to create hybrid classes by linking across different base classes.
To use a decorator pattern and still get proper access to everything, each class (in the programming sense of the word) needs to be implemented properly as a decorator class.
For instance:
public class BaseClass
{
protected BaseClass(BaseClass underlyingCharacterClass);
public abstract bool CanCastSpells();
public abstract List<Spell> GetAvailableSpells();
protected BaseClass UnderlyingCharacterClass;
}
public class Wizard : BaseClass
{
public override bool CanCastSpells() { return true; }
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
result.Add(new WizardSpell1());
...
return result;
}
}
public class Thief : BaseClass
{
public override bool CanCastSpells()
{
if (UnderlyingCharacterClass != null)
return UnderlyingCharacterClass.CanCastSpells();
return false;
}
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
return result;
}
}
If the classes have some common interface or base class, then multiclass is additional class (MultiClass) which also implements this interface or base class, then delegates to its contained instances.
For example:
public class MultiClass : Class {
...
public MultiClass(params Class[] classes) {
this.classes = classes;
}
public IEnumerable<Ability> GetAbilities() {
return this.classes.SelectMany(с => c.GetAbilities());
}
...
}
If you want to add more classes, you can add AddClass method to the base Class, which would create MultiClass from single class, or recreate multiclass with one more contained class for MultiClass.
Not everyone's cup of tea, but you could use state pattern.
public interface Player
{
void Fight();
void CastSpell();
void DoRoguishThings();
}
public class PlayerImpl : Player
{
Player fighter;
Player wizard;
Player rogue;
Player current;
public void Fight(){ current.Fight(); }
public void CastSpell(){ current.CastSpell(); }
public void DoRoguishThings(){ current.DoRoguishThings; }
public void MakeWizard(){ current = wizard; }
public void GoRogue(){ current = rogue; }
}
public class Fighter : Player
{
public void Fight(){ // do fighting }
public void CastSpell()
{
Console.WriteLine("You can't cast a spell, you are but a mere pugilist.");
}
...
}
public class Wizard : Player
{
public void Fight(){ // do wizardly fighting }
public void CastSpell() { // do spell-casting }
public void DoRoguishThings() { // whatever }
}
I think your characters should be able to have multiple Facet/Role implementing "Archetypes".
Then each one having multiple skills or attributes. Let's say...
class Archetype
{
string Name;
Dictionary<string,Type> Properties;
Dictionary<string,Action> Skills;
}
class Character
{
string Name;
string Alias;
Dictionary<Archetype,Dictionary<string,object>> FacetData;
}
class TheGame
{
public static void Main()
{
var Pilot = new Archetype();
Pilot.Name = "Combat-Pilot";
Pilot.Properties.Add("FlightHours", typeof(int));
Pilot.Properties.Add("AmbientTypes", typeof(List<string>));
var Jedi = new Archetype();
Jedi.Name = "Jedi";
Jedi.Properties.Add("ForceLevel", typeof(int));
Jedi.Properties.Add("Title", typeof(string));
Jedi.Properties.Add("IsCombatVeteran", typeof(bool));
Jedi.Skills.Add("LightSaberFight", FightWithLightSaber());
var Anakin = new Character();
Anakin.Id = 100;
Anakin.Name = "Anakin Skywalker";
Anakin.Alias = "Darth Vader";
Anakin.FacetData.Add(Pilot, new Dictionary<string, object>()
{ { "FlightHours", 2500 },
{ "AmbientTypes", new List<string>() {"Atmospheric", "Space", "Hyper-Space"} } };
Anakin.FacetData.Add(Jedi, new Dictionary<string, object>()
{ { "ForceLevel", 7 },
{ "Title", "Padawan" },
{ "IsCombatVeteran", true } };
Anakin.ApplySkill(Jedi, "LightSaberFight", Target);
}
public static void FightWithLightSaber(Character Target)
{
ShowBrightLightSaberPointingTo(Target);
EmitCoolSound();
}
}
If you get the Idea, then you could store properties/data and call skills/tasks with some degree of indirection and flexibility.
Good luck!
You may want to consider composition.
interface IWarrior
{
void Slash();
}
interface IMage
{
void Cast();
}
class Warrior : IWarrior
{
public void Slash() { }
}
class Mage : IMage
{
public void Cast() { }
}
class WarriorMage : IWarrior, IMage
{
private readonly Warrior _Warrior;
private readonly Mage _Mage;
public void Slash()
{
_Warrior.Slash();
}
public void Cast()
{
_Mage.Cast();
}
}
Néstor Sánchez A. provides you with a good solution. Drop your OOP thinking for a while and read this:
http://www.devmaster.net/articles/oo-game-design/
Not every problem can be solved with plain OOP in an elegant way.
What is the best way to implement polymorphic behavior in classes that I can't modify? I currently have some code like:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
The obvious answer is to add a virtual method to the base class, but unfortunately the code is in a different assembly and I can't modify it. Is there a better way to handle this than the ugly and slow code above?
Hmmm... seems more suited to Adapter.
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
Seems like a lot of code, but it will make the client code a lot closer to what you want. Plus it'll give you a chance to think about what interface you're actually using.
Check out the Visitor pattern. This lets you come close to adding virtual methods to a class without changing the class. You need to use an extension method with a dynamic cast if the base class you're working with doesn't have a Visit method. Here's some sample code:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
I would say that the standard approach here is to wrap the class you want to "inherit" as a protected instance variable and then emulate all the non-private members (method/properties/events/etc.) of the wrapped class in your container class. You can then mark this class and its appropiate members as virtual so that you can use standard polymorphism features with it.
Here's an example of what I mean. ClosedClass is the class contained in the assembly whose code to which you have no access.
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
If whatever assembly you are referencing were designed well, then all the types/members that you might ever want to access would be marked appropiately (abstract, virtual, sealed), but indeed this is unfortunately not the case (sometimes you can even experienced this issue with the Base Class Library). In my opinion, the wrapper class is the way to go here. It does have its benefits (even when the class from which you want to derive is inheritable), namely removing/changing the modifier of methods you don't want the user of your class to have access to. The ReadOnlyCollection<T> in the BCL is a pretty good example of this.
Take a look at the Decorator pattern. Noldorin actually explained it without giving the name of the pattern.
Decorator is the way of extending behavior without inheriting. The only thing I would change in Noldorin's code is the fact that the constructor should receive an instance of the object you are decorating.
Extension methods provide an easy way to add additional method signatures to existing classes. This requires the 3.5 framework.
Create a static utility class and add something like this:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
Add a reference to the utility class on the page, and this method will appear as a member of ClassA. You can overload existing methods or create new ones this way.