Modifying type hierarchies at runtime - c#

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

Related

c# decorator pattern multiple properties wrapping multiple times [duplicate]

I just started to learn Decorator Design Pattern, unfortunately i had to go through various refrences to understand the Decorator pattern in a better manner which led me in great confusion. so, as far as my understanding is concern, i believe this is a decorator pattern
interface IComponent
{
void Operation();
}
class Component : IComponent
{
public void Operation()
{
Console.WriteLine("I am walking ");
}
}
class DecoratorA : IComponent
{
IComponent component;
public DecoratorA(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("in the rain");
}
}
class DecoratorB : IComponent
{
IComponent component;
public DecoratorB(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("with an umbrella");
}
}
class Client
{
static void Main()
{
IComponent component = new Component();
component.Operation();
DecoratorA decoratorA = new DecoratorA(new Component());
component.Operation();
DecoratorB decoratorB = new DecoratorB(new Component());
component.Operation();
Console.Read();
}
}
But can the below code also be Decorator Pattern?
class Photo
{
public void Draw()
{
Console.WriteLine("draw a photo");
}
}
class BorderedPhoto : Photo
{
public void drawBorder()
{
Console.WriteLine("draw a border photo");
}
}
class FramePhoto : BorderedPhoto
{
public void frame()
{
Console.WriteLine("frame the photo");
}
}
class Client
{
static void Main()
{
Photo p = new Photo();
p.Draw();
BorderedPhoto b = new BorderedPhoto();
b.Draw();
b.drawBorder();
FramePhoto f = new FramePhoto();
f.Draw();
f.drawBorder();
f.frame();
}
}
My Understanding
From the second example given by me, we can call all the three methods, but from the first example i wont be able to get access to all the three methods by creating a single object.
It should be a comment, but I have too many words.
For example, you have an object and interface, like Repository : IRepository.
public interface IRepository
{
void SaveStuff();
}
public class Repository : IRepository
{
public void SaveStuff()
{
// save stuff
}
}
and client, which probably was written by someone else
class RepoClient
{
public void DoSomething(IRepository repo)
{
//...
repo.SaveStuff();
}
}
And once you decided, that ALL calls to repository should be logged. But you have a problem: the Repository class is from an external library and you don't want to change that code. So you need to extend the Repository's behavior that you use. You write RepositoryLogDecorator : IRepository, and inside on each method do the logging, like
public class RepositoryLogDecorator : IRepository
{
public IRepository _inner;
public RepositoryLogDecorator(IRepository inner)
{
_inner = inner;
}
public void SaveStuff()
{
// log enter to method
try
{
_inner.SaveStuff();
}
catch(Exception ex)
{
// log exception
}
// log exit to method
}
}
So, before you could use client as
var client = new RepoClient();
client.DoSomething(new Repository());
but now you can use
var client = new RepoClient();
client.DoSomething(new RepositoryLogDecorator(new Repository()));
Note, that this is a very simple example. In real projects, where object created primary with DI container, you will be able to use decorator by changing some config.
So, decorator is used to extend functionality of object without changing object or client.
Another benefit of decorator: your decorator does not depend on Repository implementation. Only depends from an interface IRepository. Why this is an advantage? If somehow you decide to write you own implementation of IRepository
public class MyAwesomeRepository : IRepository
{
public void SaveStuff()
{
// save stuff, but AWESOME!
}
}
you will be able to automatically decorate this with decorator, which already exist
var client = new RepoClient();
client.DoSomethig(new RepositoryLogDecorator(new MyAwesomeRepository()));
Want to see example from real software? (just as sample, code is ugly, I know) => go here
There is this PatternCraft series on Youtube that explains Design Patterns with Starcraft, you should check the video about Decorators here.
In the video above the author gives an example with a Marine and WeaponUpgrade.
In the game you will have a Marine and then you can upgrade its weapon:
marine = new WeaponUpgrade(marine);
Note that you still have a marine there, it is not a new unit, it is the same unit with things that modifies its attributes.
public class MarineWeaponUpgrade : IMarine
{
private IMarine marine;
public MarineWeaponUpgrade(IMarine marine)
{
this.marine = marine;
}
public int Damage
{
get { return this.marine.Damage + 1; } // here
set { this.marine.Damage = value; }
}
}
You do that by creating a class that implements the same interface as your unit and access your unit properties to modify values.
There is a Kata on CodeWars challenging you to complete the Weapon and Armor decorators for a marine.
Per GOF page Decorator desing pattern:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
In your second example you are using inheritance to extend behaviour of a class, I believe this is technically not a Decorator design pattern.
The decorator pattern allows you to add a specific behavior to an individual object of a given type without affecting other instances of that same type.
In your second example, which is normal inheritance, all instances of the class inherit the modified behavior.
The second example is not a decorate pattern, since an essential ingredient to decorator pattern is that the object accepts one of its kind and possibly enhance it.
An instances of this in the first example is
public DecoratorA(IComponent c)
{
component = c;
}
Also, the goal of the decorator pattern is to create "one" object, then decorate it by passing it through different filters or decorators.
Hence the line
DecoratorA decoratorA = new DecoratorA(new Component());
Should be
DecoratorA decoratorA = new DecoratorA(component );

Determine what implementationt to use in C# during run time

My code talks to 4 different machines (money machines from different companies). Each one of them does:
1. Dispense
2. Deposit
let's call the machines(A,B,C,D).
In my code if I want to call Deposit from a machine I would end up with something like:
MyProject.A.Deposit()
I ended up with switch statements that are basically something like this:
Switch(machine){
case A:
MyProject.A.Deposit();
break;
case B:
MyProject.B.Deposit();
break;
}
The bigger the code gets,the problem of very long namespaces and switch statements becomes annoying.
My question is:
Is there a way I can tell the compiler to use the specific namespace during the run-time? Or Maybe by using a config variable or a string that has namespace path.
I wanted something where I can do:
Deposit();
Since i have the information of which machine I am connected to, the problem is just how to change dynamically the namespace.
Yes, assuming all four machines' Dispense and Deposit methods share the same contract, all you need is to create an interface that they all implement:
public interface IMachine
{
void Dispense();
void Deposit();
}
Then make sure you implement this same interface on all your machine concrete implementations:
public class MachineA : IMachine
{
public void Dispense()
{
// do something here
}
public void Deposit()
{
// do something here
}
}
public class MachineB : IMachine
{
public void Dispense()
{
// do something here
}
public void Deposit()
{
// do something here
}
}
public class MachineC : IMachine
{
public void Dispense()
{
// do something here
}
public void Deposit()
{
// do something here
}
}
public class MachineD : IMachine
{
public void Dispense()
{
// do something here
}
public void Deposit()
{
// do something here
}
}
I'm assuming you don't use Dependency Injection or have an IoC container currently in your system, so to keep things simple you can have a Factory to always create the IMachine instances for you:
public static class MachineFactory
{
// this is assuming you are reading the machine name from AppConfig
private static Lazy<string> _machineName = new Lazy<string>(() => ConfigurationManager.AppSettings["TargetMachine"]);
public IMachine GetMachine()
{
switch(_machineName.Value)
{
case "MachineA":
return new MachineA();
case "MachineB":
return new MachineB();
case "MachineC":
return new MachineC();
case "MachineD":
return new MachineD();
}
}
}
Now, in the rest of your application, whenever you need an instance of a machine, all you need to do is use the factory without having to worry about the different machine implementations:
var machine = MachineFactory.GetMachine();
You could go through a switch-case for the value that will decide the namespace, where you have "using NamespaceX;" inside the cases.

Why should I want to create an object with base class reference?

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()

Which design pattern can I use in my algorithm?

I would like to create two algorithm with design pattern approach. Robot should clean and return to the initial position.
After clean the room, i need the cleaned path also.
I am planing to use the Command pattern.But one doubt, requirement says both clean and return algorithem should be interchangable and required two algorithem...so i havae a doubt Stratagy is better than Command pattern?
As per command pattern I can store all the executed commands in a List and find out the path. But still I have a doubt which pattern will be best(requirement says two ago required).
Please see the design , clean and return from different interface so i think it is difficult to use factory to make interchangable...
public interface ICleaningAlgorithm {
void Clean(IRobot robot);
}
public interface IReturnAlgorithm {
void Return(IRobot robot);
}
Example classes (without implementation):
public class CleaningAlgorithm : ICleaningAlgorithm {
public void Clean(IRobot robot) {
/* pseudocode from the post */
}
}
public class ReturnAlgorithm {
public void Return(IRobot robot) {
/* some shortest path algorithm */
}
}
Design UML image attached
If you need to have two algorithms that are interchangeable at runtime, then you should look into the Factory pattern, and the Command Pattern. As Oded said, design patterns are not mutually exclusive.
For example
public interface Command
{
// First, you define a common interface for all commands.
public void execute();
}
public class Command1 implements Command
{
// Implement the execute method.
public void execute()
{
// Run some code in here.
}
}
public class Command2 implements Command
{
// Implement the execute method for the second command.
public void execute()
{
// Run some more code in here.
}
}
So, now you've defined a common interface for your commands, which means they can be referenced like this:
Command com = new Command2();
// This is an important property!
Now you will implement your Factory class:
public class CommandFactory
{
public static int ALGO_1 = 1;
public static int ALGO_2 = 2;
public Command getInstance(int discriminator)
{
// Check the value, and if it matches a pre-defined value..
switch(discriminator)
{
case ALGO_1:
return new Command1();
break;
case ALGO_2:
return new Command2();
break;
}
}
}
This means you now have a more flexible way of generating these classes, and you can use this class as follows:
CommandFactory factory = new CommandFactory();
Command com = factory.getInstance(CommandFactory.ALGO_1);
// You've just generated algorithm 1.
com.execute();
// And you've just ran the code in algorithm 1.
Edit in response
My question is, why define different interfaces? Why not have it like:
public interface Algorithm {
void execute(IRobot robot);
}
public class CleaningAlgorithm : Algorithm {
public void execute(IRobot robot) {
/* pseudocode from the post */
}
}
public class ReturnAlgorithm : Algorithm {
public void execute(IRobot robot) {
/* some shortest path algorithm */
}
}

Factory Pattern, Another Pattern or no pattern at all?

I have 2 cases wheter a method can be considered a Factory Design Pattern, this example is in C#, altought, can apply to other programming languages:
enum NinjaTypes {
Generic,
Katanna,
StarThrower,
Invisible,
Flyer
}
public class Ninja {
public string Name { get; set; }
public void jump() { ... }
public void kickAss() { ... }
}
public class KatannaNinja: Ninja {
public void useKatanna() { ... }
}
public class StarNinja: Ninja {
public void throwStar() { ... }
}
public class InvisibleNinja: Ninja {
public void becomeInvisible() {...}
public void becomeVisible() {...}
}
public class FlyNinja: Ninja {
public void fly() {...}
public void land() {...}
}
public class NinjaSchool {
// always return generic type
public Ninja StandardStudent() {...}
// may return other types
public Ninja SpecialityStudent(NinjaTypes WhichType) {...}
}
The method StandardStudent() always return a new object of the same type, the SpecialityStudent(...), may return new objects from different classes that share the same superclass / base type. Both methods are intentionally not virtual.
The question is, are both methods "Factory Design Pattern" ?
My guess is that SpecialityStudent(...) is, but StandardStudent() is not. If the second is not, can be considered another design pattern ?
I don't think that nor a FactoryMethod`nor AbstractFactory patterns forbid the user to use a parameter to specify a type to the creator method. Anyway you should consider at least 2 things in your design:
Factory methods are useful to keep the client unaware of the concrete type of the created object. From my point of view isn't wrong to specify explicitly the type of object to be created, but pay attention to not put too much knowledge on the client classes to be able to construct objects through the factory.
Both your factory methods return a Ninja object, but some of your ninjas extended class declare additional methods, which client is unaware of. If your client need to use those methods explicitly then maybe you have to make some consideration on your design.
I think this actually looks like an Anti-Pattern. There's really nothing to stop a consumer of this code to just instantiate the specialty ninjas directly. What benefit is there to using the Ninja School? I think the whole point of the Factory pattern is to encapsulate the process of instantiating an object so that you can hide the details from the consumer. Any time you make a change to the "creation" logic, it doesn't break anyone's code.
And it just looks like a bad idea to have all the types in an enum. I don't have a concrete reason to back up this claim other than, "it feels wrong".
After reviewing the Abstract Factory pattern, I can see how you could go about turning this into an Abstract Factory, but I don't see the benefit given the semantics of your objects. I think that if you want to have a Ninja factory, you'd have to make the individual constructors protected or internal, so they can't be called directly by consumer code
Both your methods can be seen as factories. But the second one is a little awkward to use:
var school = new NinjaSchool();
var ninja = school.SpecialtyStudent(NinjaTypes.Flyer);
// to fly you must cast
((FlyingNinja)ninja).Fly();
You've already asked for a flyer, so you shouldn't need to cast. A better option might be to eliminate the enum and ask for the exact ninja that you want:
var flyingNinja = school.FlyingStudent(); // you get a FlyingNinja
flyingNinja.Fly();
Another thing to consider in your design is this: what if you want an invisible ninja that can fly? Or a katana ninja that also throws stars? That will shake up your hierarchy and challenge your belief in inheritance.
It's almost a factory method. I would do something like:
enum NinjaTypes {
Generic, Katanna, StarThrower, Invisible, Flyer
}
class Ninja {
String Name;
void jump() {
}
void kickAss() {
}
void useKatanna() {
System.out.println("nothing happens");
}
void throwStar() {
System.out.println("nothing happens");
}
void becomeInvisible() {
System.out.println("nothing happens");
}
void becomeVisible() {
System.out.println("nothing happens");
}
void fly() {
System.out.println("nothing happens");
}
void land() {
System.out.println("nothing happens");
}
}
class StarThrowerNinja extends Ninja {
void throwStar() {
System.out.println("throwing star");
}
}
class NinjaSchool {
static Ninja create(NinjaTypes WhichType) {
switch (WhichType) {
case Generic:
return new Ninja();
case StarThrower:
return new StarThrowerNinja();
default:
return null;
}
}
}
public class Main {
public static void main(String[] args) {
Ninja generic=NinjaSchool.create(NinjaTypes.Generic);
generic.throwStar();
Ninja starThrower=NinjaSchool.create(NinjaTypes.StarThrower);
starThrower.throwStar();
}
}

Categories

Resources