I'm creating an abstract finite machine state class with an enum for the possible commands it can receive, something like:
public abstract class FSMBase
{
public enum Commands {};
public enum States;
public Dictionary<Transition, States> AvailableTransitions;
public States CurrentState;
public abstract void InitCommandsAndStatesAndTransitiosnAndInitialState();
public void ProcessCommand(Commands _command)
{
Transition RequestedTransition = new Transition(CurrentState, command);
if(AvailableTransitions.TryGetValue(RequestedTransition, out State nextState) //pseudocode
{
CurrentState = nextState;
}
}
}
Then in the derived class I would like to override the States, the Transitions and the Commands. Something like:
public class MyFSM : FSMBase
{
public override void InitCommandsAndStatesAndTransitiosnAndInitialState()
{
States = {Off, starting, started, ...} //HERE IS MY PROBLEM
Commands = {start, stop, finish, ...}; // HERE IS MY PROBLEM
Transitions = new Dictionary<Transition, BaseState>
{
{new Transition(States.Off, Commands.Start), States.starting},
....
}
CurrentState = States.Off;
}
}
How do I override the enums in my derived class ???
Well, enum is in fact int (byte, short, long ect.) and can't be overriden. I suggest using generics instead
public abstract class FSMBase<State, Command>
where State : Enum // : Enum wants C# 7.3+
where Command : Enum {
//TODO: I suggest have these fields private, or at least, protected
public Dictionary<Transition, State> AvailableTransitions;
public State CurrentState;
public void ProcessCommand(Command _command) {
...
}
}
When implementing MyFSM you can put required enums:
public class MyFSM : FSMBase<MyStates, MyCommands> {
...
}
Edit: in case of lower c# versions you can try same idea but different constraints:
public abstract class FSMBase<State, Command>
where State : struct
where Command : struct {
public State CurrentState;
...
// Instead of compile time error we are going to have runtime one,
// if either State or Command is not enum
static FSMBase() {
if (!typeof(State).IsEnum)
throw new InvalidCastException("Generic pararameter State must be enum!");
else if (!typeof(Command).IsEnum)
throw new InvalidCastException("Generic pararameter Command must be enum!");
}
}
...
public class MyFSM : FSMBase<MyStates, MyCommands> {
public override void InitCommandsAndStatesAndTransitiosnAndInitialState() {
...
CurrentState = MyStates.Off;
...
}
...
}
Related
I'm having troubles thinking of the design for my assignment.
for the assignment I would have 2 inheritance hierarchies and I would need to mimic multiple inheritance functionalities and the cross product so robotDog, robotBigDog, robotSmallDog, attackRobotDog, etc... it seems just doing multiple inheritance would end up being 9 different class files which is probably not the best approach.
for instance:
public class dog{
public virtual void bark{ Console.WriteLine("woof")};
}
public class bigDog : dog{
public override void bark{ Console.WriteLine("WOOF")};
}
public class smallDog : dog{
public override void bark{ Console.WriteLine("arf arf")};
}
public class robot{
public virtual void action{ Console.WriteLine("moves")}
}
public class attackRobot : robot{
public virtual void action{ Console.WriteLine("attacks")}
}
public class serviceRobot : robot{
public virtual void action{ Console.WriteLine("serves")}
}
I was instead thinking of doing a double composition of one class containing a dog and a robot because smallDog and bigDog can stand in for dog and attackRobot and serviceRobot can stand in for robot.
public class robotDog{
dog myDog;
robot myRobot;
public robotDog(dog typeDog, robot typeRobot){
myDog = typeDog;
myRobot = typeRobot;
}
.
. various functionality
.
}
is it a practical design to use double composition and also have a constructor that ask for a dog and robot? Or is there a different way to think/approach this?
You can not have multiple inheritance in C#, but you can have multiple interfaces.
You can use interfaces to define what a dog and a robot look like, create some different flavours of dog and robot, then combined them into a RobotDog class that has some defaults that can be overridden, i.e.
using System;
namespace ConsoleApp1
{
public interface IDog
{
void bark();
}
public interface IRobot
{
void action();
}
public class dog : IDog
{
public virtual void bark() { Console.WriteLine("woof"); }
}
public class bigDog : dog
{
public override void bark() { Console.WriteLine("WOOF"); }
}
public class smallDog : dog
{
public override void bark() { Console.WriteLine("arf arf"); }
}
public class robot : IRobot
{
public virtual void action() { Console.WriteLine("buzz, click"); }
}
public class attackRobot : robot
{
public override void action() { Console.WriteLine("attacks"); }
}
public class serviceRobot : robot
{
public override void action() { Console.WriteLine("attacks"); }
}
public interface IRobotDog : IDog, IRobot
{
IDog dog { get; set; }
IRobot robot { get; set; }
}
public class RobotDog : IRobotDog
{
public IDog dog { get; set; }
public IRobot robot { get; set; }
public RobotDog()
{
dog = new dog();
robot = new robot();
}
public RobotDog(IDog dogType)
{
dog = dogType;
robot = new robot();
}
public RobotDog(IRobot robotType)
{
dog = new dog();
robot = robotType;
}
public RobotDog(IDog dogType, IRobot robotType)
{
dog = dogType;
robot = robotType;
}
public void bark() { dog.bark(); }
public void action() { robot.action(); }
}
class Program
{
static void Main(string[] args)
{
RobotDog robotDog = new RobotDog();
robotDog.bark();
robotDog.action();
robotDog = new RobotDog(new bigDog(), new attackRobot());
robotDog.bark();
robotDog.action();
robotDog = new RobotDog(new bigDog());
robotDog.bark();
robotDog.action();
robotDog = new RobotDog(new attackRobot());
robotDog.bark();
robotDog.action();
robotDog = new RobotDog();
robotDog.dog = new bigDog();
robotDog.bark();
robotDog.action();
}
}
}
I would like to expand just a bit from what Xavier has offered. An interface is nothing more than a "contract". In its simplest form, any class that inherits an interface MUST declare the functions / methods / properties within it. So this way, any other object attempting to rely on its defined exposed components knows that it can, and they wont be missing. Now, you as the developer can implement that however you want and even have an empty function, provided the function actually exists but otherwise does nothing.
public interface IDog
{
void bark();
}
public interface IRobot
{
void action();
}
First, just simple dog or robot. Notice each implements their respective "REQUIRED" methods from the interface.
public class Dog : IDog
{
public void bark()
{
Console.WriteLine("Woof");
}
}
public class Robot : IRobot
{
public void action()
{
Console.Write("Activate jet pack, fly");
}
}
Notice below, the robotic dog never has an actual Dog or Robot class of its own. However, it DOES implement both individual requirements of each interface respectively into one major class of both.
public class RoboticDog : IDog, IRobot
{
public void bark()
{
Console.WriteLine("Woof -beep- woof");
}
public void action()
{
Console.Write("Activate jet pack, flying with fur");
}
}
Now, lets see how they operate individually.
static void Main(string[] args)
{
object testDog = new Dog();
object testRobot = new Robot();
object testBoth = new RoboticDog();
WhatCanIDo(testDog);
WhatCanIDo(testRobot);
WhatCanIDo(testBoth);
}
public void WhatCanIDo( object theThing )
{
// Here I am checking if the object is of a class type
// the inherits from IDog. If so, I can type-cast it as such
// and then call its "bark()" method as required to exist from interface.
if (theThing is IDog)
((IDog)theThing).bark();
// likewise if the object has interface of an IRobot
if (theThing is IRobot)
((IRobot)theThing).action();
}
I created a small console application for you with some small tips on how to catch when you need an interface over a base class, or vice-versa.
using System;
namespace ConsoleApp6
{
class Program
{
interface IWalkable
{
void Walk(int xAxis, int yAxis);
}
class Robot : IWalkable
{
public int RobotId { get; set; }
public Robot(int robotId)
{
RobotId = robotId;
Console.Write("Robot created! \n");
}
public void Walk(int xAxis, int yAxis)
{
Console.WriteLine("Im walking beep boop");
Console.WriteLine("*walks*");
Console.WriteLine($"Ended up in X: {xAxis} y:{yAxis}");
}
}
class BadRobot : Robot
{
public BadRobot(int robotId) : base(robotId)
{
}
}
class Dog : IWalkable
{
public Dog()
{
Console.Write("Dog created! \n");
}
public void Walk(int xAxis, int yAxis)
{
Console.WriteLine("Im walking, roof roof");
Console.WriteLine("*walks*");
Console.WriteLine($"Ended up in X: {xAxis} y:{yAxis}");
}
public virtual void Breath()
{
Console.WriteLine("I breath normal");
}
}
class BadDog : Dog
{
public override void Breath()
{
Console.WriteLine("I breath normal");
Console.WriteLine("But then I bark, because im bad");
}
//I can't "extend" an interface
//but I can extend a virtual method from the base class
}
static void Main(string[] args)
{
//three tips over inheritance
//1. If you want to abstract some *behavior*, you probably want an interface:
//for example here, both dogs and robots can walk. They are going to do that
//on their own way, so each need their own proper implementation,
//but the actions is the same thus, the interface
// An interface is meant to group objects over shared functionality
//so for example I can later do something like this
var dog = new Dog();
var badDog = new BadDog();
var badRobot = new BadRobot(1);
// these function doesn't care if its a dog or a robot
void WalkOverThere(IWalkable walkable)
{
//some other code...
walkable.Walk(5, 10);
}
//The key here is that the object pass over parameter implements the IWalk interface
WalkOverThere(badDog);
WalkOverThere(badRobot);
//Please notice that for each class that inherits "IWalkable"
//There will be a new implementation, so in this case, if
//all the robots inherit from the class robot, all will walk the same way
//In that, I cannot extend, or modify how that method is performed in the base
//class from the child class
//2. Now, the case is different when we talk about some functionality that could change
//for any child implementation of the base class. Think about the breath functionality
//A robot can't breathe, but a dog does. And given that every dog breaths differently
//it makes sense to create and virtual method, that means that I can reconfigure how
//the breath method behaves. For example:
dog.Breath();
badDog.Breath();
//3. Another thing that is useful to take into account is that
//whenever I can't create a given object without some piece of information,
//it makes sense to create the necessity of that data in the constructor.
//take for example in this code that I cannot create a robot without a valid int robotId
//This practice enforces me to create a robot like:
//var robot = new Robot(100); where 100 is the id
//var robot = new Robot(); the compile would not allow that
}
}
}
I'm having difficulty inheriting from a generic class that is itself inherited from a generic singleton.
I am trying to make an inventory base class that is a singleton and derive different inventory types from this with different derived items.
Code has been simplified for brevity.
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
public static T Instance
{
get
{
if (m_ShuttingDown)
return null;
lock (m_Lock)
{
if (m_Instance == null)
{
m_Instance = (T)FindObjectOfType(typeof(T));
if (m_Instance == null)
{
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
public class Inventory<T> : Singleton<Inventory<T>> where T : Item
{
...
}
public class EquipmentInventory : Inventory<Equipment>
{
...
}
public class Item : ScriptableObject
{
public string Name = "Item";
}
public class Equipment : Item
{
public string Name = "Equipment";
}
I can't access the Instance;
private EquipmentInventory equipmentInventory;
private Inventory<Item> inventory;
public void Run()
{
var cachedInventory = Inventory<Item>.Instance; //returns null
var cachedEquipmentInventory = EquipmentInventory.Instance as EquipmentInventory; //returns null
}
Both statements return null.
The purpose of this, is that each inventory type will be a singleton and each type of inventory will be implent different item types, so that the base inventory will use the Item type, while the Equipment inventory will be implemented using the Equipment item type.
Here is an alternate method, which seems to solve this
public abstract class Inventory<T, TClass>
: Singleton<TClass> where TClass
: MonoBehaviour where T : Item
{
}
public class EquipmentInventory : Inventory<Equipment, EquipmentInventory>
{
}
I haven't fully tested this yet with actual code, but will update when I have tested it more thoroughly
Please assist.
The main issue is caused by
public class Inventory<T> : Singleton<Inventory<T>> : where T : Item { }
Here you "pass in" the generic type Iventory<T> into the Singleton even though later you explicitly inherit from that Inventory<T> class.
Here is one possible solution though it might seem like a bit strange workaround at first:
Make your Inventory take a second generic type, use the first one inside the class as needed and "forward" the second one to the Singleton<T> like e.g.
// Note how for the limitation via where you still can use the generic type
// which makes sure no other MonoBehaviour can be passed to TSelf by accident
public class Inventory<TItem, TSelf> : Singleton<TSelf> where TItem : Item where TSelf : Inventory<TItem,TSelf>
{
public TItem reference;
private void Awake()
{
if (!reference) reference = ScriptableObject.CreateInstance<TItem>();
}
}
Then in the implementation your pass additionally in your own final (non-generic) type so it can be properly "forwarded" to the Singleton<T> like e.g.
public class EquipmentInventory : Inventory<Equipment, EquipmentInventory> { }
Note that anyway this class has to be in a separated file called EquipmentInventory.cs otherwise it won't work as component in Unity.
This works now since now you explicitly pass in the type EquipmentInventory for TSelf which is then forwarded to the Signleton<T> so the return type of Instance is explicitly EquipmentInventory.
In general get used to rather have one script file for each individual class/type.
Additionally I would slightly alter your fields in Item and Equipment like e.g.
[CreateAssetMenu]
public class Item : ScriptableObject
{
[SerializeField] private string _name;
public string Name => _name;
private void Awake()
{
_name = GetName();
}
protected virtual string GetName()
{
return nameof(Item);
}
}
and
[CreateAssetMenu]
public class Equipment : Item
{
protected override string GetName()
{
return nameof(Equipment);
}
}
And this is how it looks like e.g.
public class Example : MonoBehaviour
{
public EquipmentInventory equipmentInventory;
[ContextMenu("Run")]
public void Run()
{
equipmentInventory = EquipmentInventory.Instance;
}
}
I'm trying to create my own state machine but ran into some trouble regarding lists of classes with generic type. My code is as below.
State.cs:
using UnityEngine;
using System.Collections;
public abstract class State<T> where T:StateMachine
{
public T sm;
public State()
{
}
public virtual void OnEnter()
{
sm.currentState = sm.futureState;
}
public abstract void OnExit();
public abstract void OnLoop();
}
StateMachine.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public abstract class StateMachine : MonoBehaviour
{
public List<State<T>> stateList = new List<T>>();
public int currentState = -1;
public int futureState;
protected virtual void Start()
{
foreach (State<T> s in stateList)
{
s.sm = this;
}
}
protected virtual void Update()
{
if (currentState != futureState)
{
stateList[futureState].OnEnter();
}
stateList[currentState].OnLoop();
if (currentState != futureState)
{
stateList[currentState].OnExit();
}
}
}
TestStateMachine.cs:
using UnityEngine;
using System.Collections;
public class TestStateMachine : StateMachine
{
public enum StateNames:int
{
State1,
State2,
};
public KeyCode kc;
// Use this for initialization
protected override void Start ()
{
stateList.Add(new TestStateMachineFirstState());
stateList.Add(new TestStateMachineSecondState());
base.Start();
}
}
public class TestStateMachineFirstState : State<StateMachine>
{
public override void OnEnter()
{
Debug.Log("SM1 OnEnter");
base.OnEnter();
}
public override void OnLoop()
{
Debug.Log("SM1 OnLoop");
if (Input.GetKeyDown(sm.kc))
{
sm.futureState = (int)TestStateMachine.StateNames.State2;
}
}
public override void OnExit()
{
Debug.Log("SM1 OnExit");
}
}
public class TestStateMachineSecondState : State<StateMachine>
{
public override void OnEnter()
{
Debug.Log("SM2 OnEnter");
base.OnEnter();
}
public override void OnLoop()
{
Debug.Log("SM2 OnLoop");
if (Input.GetKeyDown(sm.kc))
{
sm.futureState = (int)TestStateMachine.StateNames.State1;
}
}
public override void OnExit()
{
Debug.Log("SM2 OnExit");
}
}
I get error CS0246: Type or namespace name T cannot be found (or something that sounds similar).
My state machine "functions" if I replace all State<T> and State<TestStateMachine> with State<StateMachine> and the if (Input.GetKeyDown(sm.kc)) with (Input.GetKeyDown(KeyCode.A)).
But that is not ideal as I would not be able to get variables from the children state machines. Is there a way to keep this structure(as bad as it might be), or should I try another approach in doing state machines?
One might note that if you look at the compiler error message, it will specify the source file and the line number at which the error was detected. That usually helps identify the problem.
The problem is this:
public abstract class StateMachine : MonoBehaviour
{
public List<State<T>> stateList = new List<T>>();
...
T has no meaning in this class as it's not an generic class or method. Hence, the compiler has no idea what to do with State<T> or List<T.
A second problem is that
public List<State<T>> stateList = new List<T>>();
wouldn't compile even if in a suitable generic class or method: List<State<T>> is not a compatible type with List<T>.
The reason you get this compilation error is because you are using type parameter T of type State in the StateMachine class. You could employ the curiously recurring template pattern:
class State<T> where T : StateMachine
class StateMachine<T> where T : StateMachine
class RealStateMachine : StateMachine<RealStateMachine>
However, this might be very confusing. If you are able, you should consider a design where State is a nongeneric abstract class or interface.
public abstract class State<T>
{
public virtual Enter(T item)
{
// an empty method
}
}
public class ChaseState : State<FieldPlayer>
{
public override Enter(Player pl)
{
// ...
pl.Fsm.CurrentState = ChaseState.Instance;
//...
}
}
public class TendGoal : State<Goalkeeper>
{
public override Enter(Goalkeeper gk)
{
// ...implementation
gk.Fsm.CurrentState = TendGoal.Instance;
// ...implementation
}
}
public class DefendState : State<Team>
{
public override Enter(Team team)
{
// ....
team.Fsm.CurrentState = DefendState.Instance;
//.....
}
}
"Goalkeeper" and "FieldPlayer" inherit from an abstract class "Player", while "Team" inherits from another class.
public class FSM
{
public /*some type*/ owner; // PROBLEM 1
// OWNER CAN BE TEAM, GOALKEEPEEPER
// OR FIELD PLAYER
public /*some type*/ globalState;
public /*some type*/ currentState;
public /*some type*/ previousState;
public void Update()
{
if (globalState != null)
{
globalState.Execute(owner); // PROBLEM 2
// IF GLOBAL STATE'S TYPE
// IS AN OBJECT, CANT CALL EXECUTE
// OBJECTS TYPE WILL BE KNOWN ONLY
// DURING RUNTIME
}
}
}
Each object of type "Goalkeeper", "FieldPlayer" and "Team" will have a State Machine instance. The problem is.. generics cant be properties.
What should I do ?
If you make State an ordinary interface, not generic, and have its Enter method take another interface that your teams, goalkeeprs, players, etc all implement (it can even just be empty), it ought to work.
public interface IOwner {}
public interface IState
{
void Enter(IOwner item);
}
public class ChaseState : IState
{
public void Enter(IOwner pl)
{
// ...
//...
}
}
public class Player :IOwner { }
public class Something {
IOwner owner = new Team();
IState globalState = new ChaseState();
IState currentState = new DefendState();
public void Update()
{
if (globalState != null)
{
globalState.Enter(owner);
}
else if (currentState != null)
{
currentState.Enter(owner);
}
}
}
After reading your code some more, an Abstract Class is unnecessary here. You should convert State to an interface, ex: IState and remove the generic signature from it. Then your properties in your FSM object can all be public IState globalState, etc..
I would like to refer to the example that was used before on SO
with the Duck and Electric Duck:
public interface IDuck
{
void Swim();
}
public class Duck : IDuck
{
public void Swim()
{
//do something to swim
}
}
public class ElectricDuck : IDuck
{
public void Swim()
{
if (!IsTurnedOn)
return;
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}
The original violation for LSP would look like this:
void MakeDuckSwim(IDuck duck)
{
if (duck is ElectricDuck)
((ElectricDuck)duck).TurnOn();
duck.Swim();
}
One solution by the author was to put the Logic inside the electric duck's swim method to turn itself on:
public class ElectricDuck : IDuck
{
public void Swim()
{
if (!IsTurnedOn)
TurnOn();
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}
I have come across other scenarios where an extended interface can be created that supports some sort of initialization:
public interface IInitializeRequired
{
public void Init();
}
Electric Duck could then be extended with this interface:
public class ElectricDuck : IDuck, IInitializeRequired
{
public void Swim()
{
if (!IsTurnedOn)
return;
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
#region IInitializeRequired Members
public void Init()
{
TurnOn();
}
#endregion
}
EDIT: The reason for the extended interface Is based on the author saying that turning on automatically in the swim method might have other undesired results.
Then the method instead of checking and casting to a specific type can look for an extended interface instead:
void MakeDuckSwim2(IDuck duck)
{
var init = duck as IInitializeRequired;
if (init != null)
{
init.Init();
}
duck.Swim();
}
The fact that i made the initialization concept more abstract then to create an extended interface called IElectricDuck with TurnOn() method, may make this seem that I did the right thing, however the whole Init concept may only exist because of electric duck.
Is this a better way/solution or is this just an LSP violation in disguise.
Thanks
It's an LSP violation in disguise. Your method accepts an IDuck, but it requries verification of the dynamic type (whether the IDuck implements IInitializeRequired or not) to work.
One possibility to fix this would be to accept the fact that some ducks require initialization and redefine the interface:
public interface IDuck
{
void Init();
/// <summary>
/// Swims, if the duck has been initialized or does not require initialization.
/// </summary>
void Swim();
}
Another option is to accept that an uninitialized ElectricDuck is not really a duck; thus, it does not implement IDuck:
public class ElectricDuck
{
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
public IDuck GetIDuck()
{
if (!IsTurnedOn)
throw new InvalidOperationException();
return new InitializedElectricDuck(); // pass arguments to constructor if required
}
private class InitializedElectricDuck : IDuck
{
public void Swim()
{
// swim logic
}
}
}
I would still consider your final example as an LSP violation because logically you do exactly this. As you said, there is no concept of initialization really, it is just made up as a hack.
Indeed, your MakeDuckSwim method should not know anything about any duck's specifics (whether it should be initialized first, fed with some destination after initialization, etc).
It just has to make the provided duck swim!
It is hard to tell on this example (as it is not real), but looks like somewhere "upper" there is a factory or something that creates you a specific duck.
It it possible that you miss the concept of a factory here?
If there was one, then It should know what duck it is creating exactly so probably it should be responsible to know how to initialize a duck, and the rest of your code just works with IDuck without any "ifs" inside behavioral methods.
Obviously you can introduce the concept of "initialization" straight to IDuck interface. Say, a "normal" duck needs to be fed, an electrical one needs to be turned on, etc :) But it sounds a bit dodgy :)
I think first you need to answer this question about electric ducks - do they turn themselves on automatically when someone asks them to swim? If so, turn them on in the Swim method.
If not, it is the duck's client responsibility for turning it on, and you might as well just throw an InvalidOperationException if the duck can't swim because it's turned off.
public interface ISwimBehavior
{
void Swim();
}
public interface IDuck
{
void ISwimBehavior { get; set; }
}
public class Duck : IDuck
{
ISwimBehavior SwimBehavior { get { return new SwimBehavior(); }; set; }
}
public class ElectricDuck : IDuck
{
ISwimBehavior SwimBehavior { get { return new EletricSwimBehavior(); }; set; }
}
The behaviour classes:
public class SwimBehavior: ISwimBehavior
{
public void Swim()
{
//do something to swim
}
}
public class EletricSwimBehavior: ISwimBehavior
{
public void Swim()
{
if (!IsTurnedOn)
this.TurnOn();
//do something to swim
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}
Maybe something like this:
public interface IDuck
{
bool CanSwim { get; }
void Swim();
}
public class Duck : IDuck
{
public void Swim()
{
//do something to swim
}
public bool CanSwim { get { return true; } }
}
public class ElectricDuck : IDuck
{
public void Swim()
{
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
public bool CanSwim { get { return IsTurnedOn; } }
}
Client would be changed like:
void MakeDuckSwim(IDuck duck)
{
if (duck.CanSwim)
{
duck.Swim();
}
}