I've been programming in C# (as well as a few other languages) for some time now, but just recently decided that I should start writing custom classes to get a better feel for Object-Oriented Programming. To that end, I started with a base class of Vehicle, and some derived classes, to work on inheritance.
What I'm trying to do here is set up some default values and logic in the base calss of Vehicle, while having the derived classes implement some information which determines the differences. For example, while I set up the _wheelsNumber, _motorType, and _horsePower variables and logic in the base class, I would have each class (Car, Truck, Semi, Moped, etc.) set its _wheelsNumber and trigger the flow of logic to calculate out the rest of the properties.
However, I'm not sure I've built my classes in the right fashion to achieve those ends. I'm not clear on whether I'm even remotely doing the right things with my construcor and my get/set accessors (as I don't want the user to be choosing things like how many wheels a Car has, I haven't declared set accessors). One thing I think I've noticed is that the user would have to ask the program for the number of wheels before the motor type and that before the horsepower. I think this is because they're not calculated within the constructor, but I'm not certain.
Anyone clarity would be vastly appreciated.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace VehicleClasses
{
abstract public class Vehicle
{
protected const int smallMotor = 1;
protected const int mediumMotor = 3;
protected const int largeMotor = 5;
protected const int largerMotor = 7;
protected const int hugeMotor = 9;
protected const int wrongMotor = 9001;
public Vehicle()
{
_horsePower = (_motorType * _motorType) * 8;
}
protected int _wheelsNumber;
public int wheelsNumber
{
get
{
return _wheelsNumber;
}
}
protected int _motorType;
public int motorType
{
get
{
if (_wheelsNumber < 4)
{
_motorType = smallMotor;
}
else if (_wheelsNumber >= 4 && wheelsNumber <= 6)
{
_motorType = mediumMotor;
}
else if (_wheelsNumber > 6 && wheelsNumber < 10)
{
_motorType = largeMotor;
}
else if (_wheelsNumber >= 10 && wheelsNumber < 18)
{
_motorType = largerMotor;
}
else if (_wheelsNumber >= 18)
{
_motorType = hugeMotor;
}
else
{
_motorType = wrongMotor;
}
return _motorType;
}
}
protected int _horsePower;
public int horsePower
{
get
{
return _horsePower;
}
}
}
}
This is a common misapplication of inheritance. Subclasses should extend behavior, not just modify the values of state.
In your example, there is only one free variable, the number of wheels. Everything else is a derived trait based on that. Change the constructor of vehicle to take the number of wheels as an argument, then (if desired) you can add public static methods to the class like "CreateMotorcycle()" that create a vehicle with the correct number of wheels.
Alternate Suggested Exercise
Like I mentioned before, inheritance is useful when you want to extend behavior. For example, lets say you have an "Employee" base class. To keep things simple, lets say each Employee has one junior and one senior.
Whenever an employee wants time off, they have to ask their senior, but not every employee can approves. The request has to get passed up the chain until it reaches a "Manager", which is a derived instance.
Flipping it around, lets say the most senior employee is the owner. When he wants the company to do something, he doesn;t do it himself. He sends the command down the chain. Each layer might modify what needs to be done. For example, the owner says it needs to be done in 365 days, each manager says it has half the time he was told, and the worker completes the task.
Each "class" in these examples (Worker/Manager/Owner) behave differently when the same method is called. But having them all implement the same base class makes it easy to chain them together! this is a variant on the "Chain of Responsibility" and "Decorator" patterns.
Related
I am 57 years old. Other than using C# for analysing text data, my knowledge of C# is very limited. However, occasionally I try to learn some other aspects of C#. I also prefer to understand code created for windows applications rather than for console applications.
Could anyone please elaborate on the code given below which is taken from MSDN site with simple practical examples so that I can learn something from it. I think I need to create another class but how to implement it all and call it from a button in C#. Why do they say only derived classes can call 'AddGas'. Thanks in advance.
abstract class Motorcycle
{
// Anyone can call this.
public void StartEngine() {/* Method statements here */ }
// Only derived classes can call this.
protected void AddGas(int gallons) { /* Method statements here */ }
// Derived classes can override the base class implementation.
public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }
// Derived classes must implement this.
public abstract double GetTopSpeed();
}
Let that you want to create a specific Motorcycle for instance a Yamaha that has another method that returns the color of the Motorcycle. Instead of creating all the method in Motorcycle from scratch for each motorcycle you want to create you could inherit from it as below:
public class Yamaha : Motorcycle
{
public string GetColor()
{
// ....
return "Red";
}
// When a method in class is marked as abstract,
// all the class that inherit should provide an implementation
// of this method. Otherwise you would get a compilation error.
public double GetTopSpeed()
{
return 200;
}
// When a method is marked as virtual, we have two options for the derived classes.
// 1. Use the implementation provided int the base class.
// 2. Override this implementation, define a method like below and provide
// your implementation.
public override int Drive(int miles, int speed)
{
/* Method statements here */ return 2;
}
}
Furthermore, it's important to note here that you can't instantiate an abstract class (you can't create an object as new Motorcycle()).
Why do they say only derived classes can call 'AddGas' ?
Because AddGas is marked as protected. Reading about access modifiers in C# would make this and other related things more clear.
Abstract classes are just templates or guides for how to make something.
In your example, it's a guide for how to make a Motorcycle. You can't actually create a Motorcycle. You can't go into a dealership and ask for one Motorcycle please.
A Honda? Kawasaki? 150cc? 650cc? What?
Your guide tells you that:
It should be able to be started by someone (*public* void StartEngine())
Internally, should be able to add some petrol - sorry, British - (*protected* void AddPetrol(int litres))
It should be able to be driven by someone (*public* virtual int Drive(int miles, int speed))
It has a top speed that someone can read (*public* abstract double GetTopSpeed())
From this, we can see that anyone can start it, drive it, and get it's top speed.
We can also see that the bike itself can add some petrol to itself (it's an internal combustion engine, after all).
You decide on a Honda. Why? Because that's the first Make that comes to mind. So you ask for that one over there. The salesman tells you ah, that's a good starter one, no frills, no extras, it just works. It's a
public class HondaBasic : Motorcycle {
public override double GetTopSpeed()
{
return 60.0;
{
}
It's cute! You should take it out for a spin...
static void Main(string[] args)
{
// "Aww, it looks like something a child would ride!"
var bike = new HondaBasic();
bike.StartEngine();
// "Wow, is that in MPH or Km/h? Either way I could run faster than that!"
var top = bike.GetTopSpeed();
// "Well, lets take it for a spin, at least..."
bike.StartEngine();
var driven = bike.Drive(3, 30);
}
And so there you go, you took your Honda Basic out for a test drive, for 3 miles at 30 MPH.
I'm going to take liberties here and assume that Drive returns the time actually driven, because I figure time is what you get out when you give something a speed and distance.
Apparently you planned to go out for 3 miles at 30 MPH, and you apparently drove for... 1. Because that's what it said you did...
public virtual int Drive(int miles, int speed) { return 1; }
driven == 1 because the base class just returns 1 all the time! I doubt you managed 3 miles - at 30mph - in 1 minute?second? Not important.
I guess as there's nothing around to call AddGas, it probably ran out after only 1 minute?second?...
Well, that was awful. Why did they even make that model? Ok, what about that sweet thing in the corner? It's shiny! And looks as though it was actually build by people that knew... anything at all, to be honest.
public class KawasakiNinja : Motorcycle {
private int _gas;
public KawasakiNinja()
{
_gas = 100;
}
public override int Drive(int miles, int speed)
{
var timeWhateverValue = miles / speed;
_gas -= timeWhateverValue;
return timeWhateverValue;
}
public override double GetTopSpeed()
{
return 300;
}
protected override void AddGas(int gallons)
{
_gas += gallons;
}
public void FillErUp(int gallons)
{
AddGas(gallons);
}
}
Well ok then... This bike looks to actually be something more than a disposable camera with wheels. It can actually be filled up!
Sounds good! Let's take her for a spin!
static void Main(string[] args)
{
// "Mmm, shiny"
var bike = new KawasakiNinja();
// "Purrs like a kitten!"
bike.StartEngine();
// "How fast?!"
var top = bike.GetTopSpeed();
// "Sweet..."
var driven = bike.Drive(1, 300);
// "Holy cap it really can go 300! I bet it burns up fuel like there's no tomorrow, though! Let's pull over"
bike.FillErUp(50);
// "Enough to get back to the lot"
driven = bike.Drive(1, 40);
}
Quite adventurous of you - burning away a single mile at 300 mph! According to Kawasaki's (our) maths, you drove that in 0 minutes?seconds?
Aaaand it had a way to fill the tank (and, frankly, this model actually had a tank).
So, there's something moderately basic for you.
The abstract class itself just describes how to do things. It may or may not include any actual functionality;
It did specify the Drive method, and implemented it - albeit in a basic way
It specified a GetTopSpeed method, but did not implement it (abstract). That method needs to be implemented in anything made from the abstract class - compiler complains at you if you miss that out, so it's easy enough to not miss
Anything derived from the abstract classes have access to everything the abstract class can do, and, if it's virtual, can override it's implementation. Alternatively, it may actually need to provide an implementation of some kind; where the abstract base knows that it will need to be able to something, but not exactly know what or how.
In the above example, it doesn't make sense that a non-existent bike would have a top speed at all - but we know that any real bike in general will have one - so any real bikes need to provide it.
I'm working on a personal project for a friend and have hit a bit of a roadblock. I can continue as I am and write some really redundant code, but I feel there must be a more efficient way of doing this.
What I'm trying to do is write a method that will add three values and display the results to the text box under "Skill Modifier" header (see screenshot). I need to get the method, or a series of methods, to do that for each skill. It needs to get the Skill Modifier value for Balance, Climb, Escape Artist, etc...
The method would be something like "CalculateSM"
What I have currently:
private void btnUpdate_Click(object sender, EventArgs e)
{
//AM + R + MM =SM
//AM = Ability Modifier
//R = Rank
//MM = Misc Modifier
//SM = Skill Modifier
decimal balanceMod = balanceAM.Value + balanceR.Value + balanceMM.Value;
balanceSM.Text = balanceMod.ToString();
decimal climbMod = climbAM.Value + climbR.Value + climbMM.Value;
climbSM.Text = climbMod.ToString();
//etc...
}
Essentially the biggest issue, for me, is figuring out how to contrive a method that can deal with so many different field names and add them in the same way. I'd like to avoid copy and pasting the same two lines of code fifty times over for each and every skill.
Any ideas would be much appreciated! Thank you.
using fields like this is not very object-oriented. you're probably going to want to introduce a Skills class that implements the method to calculate the final skill score and then use some Skills objects for different skills.
public class Skill
{
int ability, rank, misc;
public Skill(int ability, int rank, int misc)
{
this.ability = ability;
this.rank = rank;
this.misc = misc;
}
public int Score { get { return ability + rank + misc; }
}
Skill balance = new Skill(10, 1, 1);
textBalance.Text = balance.Score.ToString();
Skill programming = new Skill(10, 100, 0);
textProgramming.Text = programming.Score.ToString();
also, think of a clever way to tie the skills to your user controls. you're not going to like ending up with 50 text boxes that are all alike except for a bit of a name. a first step could be to wire them all up to the same event handler, for example.
Normally, the approach would be to create a class which represents one row of your skills screen. You could then keep a list of these in some way (say, List<Skill>). You could then quite easily loop through all of them:
foreach (Skill skill in character.Skills)
{
// do something with the skill object
}
The trick would be to dynamically generate the user interface. It's not actually very hard to do this (although a bit too much code to go into here), by far the easiest approach would be to use something like a DataGridView. It should be fairly easy to google for examples, or just ask if you want specific info.
Looks like you have an object collection which you could databind to something in the UI (like a data grid or something)
Modify the values calculate things, what you could do in some example code:
class Skill
{
public string Name { get; set; }
public string KeyAbility { get; set; }
public int SkillModifier { get; set; }
public int AbilityModifier { get; set; }
public int Ranks { get; set; }
public int MiscModifier { get; set; }
void Calculate()
{
//Formula goes here
//Set the SkillModifier
}
}
Skill balance = new Skill() { Name = "Balance" }
Basically you can make a collection of skills, update through what ever UI object you bind to etc. Using fields the way you are atm is very redundant and using OO you can achieve the same with alot less work.
Basically in You'd create a collection of the Skill class, with Balance and all other skills you mentioned. Databind this collection to something in the UI, allow for updating, call different methods. You could even implement some inheritance for different type of skills. With a Skill base class.
What type are balanceAM, balanceR etc?
Can they not derive from a base type or interface that you can use to pass to a helper method?
private string GetText(IModel modelAM, IModel modelR, IModel modelMM)
{
return modelAM.Value + modelR.Value + modelMM.Value;
}
balanceSM.Text = this.GetText(balanceAM, balanceR, balanceMM);
Ok, the fact that you only have private fields for each individual control is your core problem. You're probably better off creating a list of structs to store them:
struct PickYourOwnNameHere
{
Control SM;
Control AM;
Control R;
Control MM;
}
List<PickYourOwnNameHere> skills = new List<PickYourOwnNameHere>();
Obviously, populate that list on initialization, and then you can just do:
skills.ForEach(skill =>
skill.SM.Text = (skill.AM.Value + skill.R.Value + skill.MM.Value).ToString()
);
I'm doing that syntax from memory, but hopefully you get the idea.
I am use to designing my applications using a more database driven approach and now I would like to start from the model. I have the following requirements and would like to get your take on it. It's basically an Activity with points associated with it.
Activity with Super 30 Doctor
Minimum 4 per month
Subtract a point if you do not hit the minimum (4)
1 Point or 2 Points if you go over 6 per month
2 Points when with a local advocate
Activity with 120 Doctor
.5 Points
Activity with Partnership
2 Points
Activity with Follow-Up Partnership Meeting
2 Points
So, I'm trying to decided if I use an inheritance hiearchy here for each activity type or an enumeration off of the activity. So, is each activity responsible for calculating their points (but in some instances then need to know the total activity count to decide) or do I have some scorer component know all the logic.
Any ideas would be great!
I have this design thus far, but I do not know where to handle the Super 30 rules:
public abstract class ActivityBase {
public int Id { get; set; }
public DateTime Date { get; set; }
public abstract double CalculatePoints();
}
public class SuperThirtyActivity : ActivityBase {
public bool WithCE { get; set; }
public bool WithLocalAdvocate { get; set; }
public override double CalculatePoints() {
if (Date.Month == 3 && Date.AddDays(7).Month == 4)
return 1;
else if (WithCE || WithLocalAdvocate)
return 2;
else
return 1;
}
}
public class OneTwentyActivity : ActivityBase {
public override double CalculatePoints() {
return .5;
}
}
public class PartnershipActivity : ActivityBase {
public override double CalculatePoints() {
return 2;
}
}
Now to handle the Super 30 rules, I thought of introducing the following class. However, some of the domain logic is leaking in here. Is this ok or any other ideas??
public class Scorer {
public double CalculateScore(IEnumerable<ActivityBase> activities) {
var score = activities.Select(a => a.CalculatePoints()).Sum();
var count = activities.Count(a => a is SuperThirtyActivity);
if (count < 4)
score--;
else if (count > 6)
score += count;
return score;
}
}
If the activity base class will contain no logic, I recommend making an IActivity interface and make 4 classes to implement it instead of inheritance. IActivity should have a method like CalculatePoints to be implemented by every realizing class.
If you are not going to check for Activity types anywhere in your application I mean if you will never have code like :
if (activity is PartnershipActivity){
//do something
}
else if (activity is FollowUpActivity) {
// do something else
}
and if you are sure there will be no new activity types introduced into the application in the future you may then consider making one Activity class with enum field as you said and do all the checks and calculations you mentioned in its business logic.
Since some of the points are based on aggregated activities, it looks like there is another concept that is not being captured in the object model, ActivityCollection. It is hinted at in the parameter to Scorer.CalculateScore, but perhaps it needs to be made explicit. The ActivityCollection could then calculate the scores since it is holding all of the information necessary.
On the other hand, the Scorer object can probably serve that role just as well. It is OK that the domain logic is in the Scorer object, since it is only the logic necessary for Scorer to do exactly what its name implies. If you keep Scorer, but move the point values from the activity classes into it, then that structure may serve just as well, if not better.
One of the most important aspects of OOP is data hiding. Can somebody explain using a simple piece of code what data hiding is exactly and why we need it?
Data or Information Hiding is a design principal proposed by David Paranas.
It says that you should hide the
design decisions in one part of the
program that are likely to be changed
from other parts of the program, there
by protecting the other parts from
being affected by the changes in the
first part.
Encapsulation is programming language feature which enables data hiding.
However note that you can do data\information hiding even without encapsulation. For example using modules or functions in non Object Oriented programming languages. Thus encapsulation is not data hiding but only a means of achieving it.
While doing encapsulation if you ignore the underlying principal then you will not have a good design. For example consider this class -
public class ActionHistory
{
private string[] _actionHistory;
public string[] HistoryItems
{
get{return _actionHistory; }
set{ _actionHistory = value; }
}
}
This calls encapsulates an array. But it does not hide the design decision of using a string[] as an internal storage. If we want to change the internal storage later on it will affect the code using this class as well.
Better design would be -
public class ActionHistory
{
private string[] _actionHistory;
public IEnumerable<string> HistoryItems
{
get{return _actionHistory; }
}
}
I'm guessing by data hiding you mean something like encapsulation or having a variable within an object and only exposing it by get and modify methods, usually when you want to enforce some logic to do with setting a value?
public class Customer
{
private decimal _accountBalance;
public decimal GetBalance()
{
return _accountBalance;
}
public void AddCharge(decimal charge)
{
_accountBalance += charge;
if (_accountBalance < 0)
{
throw new ArgumentException(
"The charge cannot put the customer in credit");
}
}
}
I.e. in this example, I'm allowing the consuming class to get the balance of the Customer, but I'm not allowing them to set it directly. However I've exposed a method that allows me to modify the _accountBalance within the class instance by adding to it via a charge in an AddCharge method.
Here's an article you may find useful.
Information hiding (or more accurately encapsulation) is the practice of restricting direct access to your information on a class. We use getters/setters or more advanced constructs in C# called properties.
This lets us govern how the data is accessed, so we can sanitize inputs and format outputs later if it's required.
The idea is on any public interface, we cannot trust the calling body to do the right thing, so if you make sure it can ONLY do the right thing, you'll have less problems.
Example:
public class InformationHiding
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
/// This example ensures you can't have a negative age
/// as this would probably mess up logic somewhere in
/// this class.
private int _age;
public int Age
{
get { return _age; }
set { if (value < 0) { _age = 0; } else { _age = value; } }
}
}
Imagine that the users of your class are trying to come up with ways to make your class no longer fulfill its contract. For instance, your Banking object may have a contract that ensures that all Transactions are recorded in a log. Suppose mutation of the Bank's TransactionLog were publically accessible; now a consuming class could initiate suspect transactions and modify the log to remove the records.
This is an extreme example, but the basic principles remain the same. It's up to the class author to maintain the contractual obligations of the class and this means you either need to have weak contractual obligations (reducing the usefulness of your class) or you need to be very careful about how your state can be mutated.
What is data hiding?
Here's an example:
public class Vehicle
{
private bool isEngineStarted;
private void StartEngine()
{
// Code here.
this.isEngineStarted = true;
}
public void GoToLocation(Location location)
{
if (!this.isEngineStarted)
{
this.StartEngine();
}
// Code here: move to a new location.
}
}
As you see, the isEngineStarted field is private, ie. accessible from the class itself. In fact, when calling an object of type Vehicle, we do need to move the vehicle to a location, but don't need to know how this will be done. For example, it doesn't matter, for the caller object, if the engine is started or not: if it's not, it's to the Vehicle object to start it before moving to a location.
Why do we need this?
Mostly to make the code easier to read and to use. Classes may have dozens or hundreds of fields and properties that are used only by them. Exposing all those fields and properties to the outside world will be confusing.
Another reason is that it is easier to control a state of a private field/property. For example, in the sample code above, imagine StartEngine is performing some tasks, then assigning true to this.isEngineStarted. If isEngineStarted is public, another class would be able to set it to true, without performing tasks made by StartEngine. In this case, the value of isEngineStarted will be unreliable.
Data Hiding is defined as hiding a base class method in a derived class by naming the new class method the same name as the base class method.
class Person
{
public string AnswerGreeting()
{
return "Hi, I'm doing well. And you?";
}
}
class Employee : Person
{
new public string AnswerGreeting()
{
"Hi, and welcome to our resort.";
}
}
In this c# code, the new keyword prevents the compiler from giving a warning that the base class implementation of AnswerGreeting is being hidden by the implementation of a method with the same name in the derived class. Also known as "data hiding by inheritance".
By data hiding you are presumably referring to encapsulation. Encapsulation is defined by wikipedia as follows:
Encapsulation conceals the functional
details of a class from objects that
send messages to it.
To explain a bit further, when you design a class you can design public and private members. The class exposes its public members to other code in the program, but only the code written in the class can access the private members.
In this way a class exposes a public interface but can hide the implementation of that interface, which can include hiding how the data that the class holds is implemented.
Here is an example of a simple mathematical angle class that exposes values for both degrees and radians, but the actual storage format of the data is hidden and can be changed in the future without breaking the rest of the program.
public class Angle
{
private double _angleInDegrees;
public double Degrees
{
get
{
return _angleInDegrees;
}
set
{
_angleInDegrees = value;
}
}
public double Radians
{
get
{
return _angleInDegrees * PI / 180;
}
set
{
_angleInDegrees = value * 180 / PI;
}
}
}
I'm building a simple game which consists of Mobiles -- the in-game characters (Mobs). Each mob can perform certain functions. In order to give that functionality to the Mob, I've created a Behavior.
For example, let's say a mob needs to move around the game field, I would give it the MoveBehavior - this is added to an internal list of Behaviors for the mob class:
// Defined in the Mob class
List<Behavior> behaviors;
// Later on, add behavior...
movingMob.addBehavior(new MovingBehavior());
My question is this. Most behaviors will manipulate something about the mob. In the MoveBehavior example, it will change the mob's X,Y position in the world. However, each behavior needs specific information, such as "movementRate" -- where should movementRate be stored?
Should it be stored in the Mob class? Other Mobs may attempt to interact with it by slowing/speeding up the mob and it's easier to access at the mob level... but not all mobs have a movementRate so it would cause clutter.
Or should it be stored in the MoveBehavior class? This hides it away, making it a little harder for other mobs to interact with - but it doesn't clutter up a non-moving mob with extra and un-used properties (for example, a tower that doesn't move would never need to use the movementRate).
This is the classic "behavioral composition" problem. The trade-off is that the more independent the behaviors are, the more difficult it is for them to interact with each other.
From a game programming viewpoint, the simplest solution is a decide on a set of "core" or "engine" data, and put that in the main object, then have the behaviors be able to access and modify that data - potentially through a functional interface.
If you want behavior specific data, that's fine, but to avoid collisions in the names of variables, you may want to make the interface for accessing it include the behavior name. Like:
obj.getBehaviorValue("movement", "speed")
obj.setBehaviorValue("movement", "speed", 4)
That way two behaviors can both define their own variables called speed and not collide. This type of cross-behavior getters and setters would allow communication when it is required.
I'd suggest looking at a scripting language like Lua or Python for this..
You could borrow a pattern from WPF (attached properties). The WPF guys needed a way to sort of attach properties to controls at run time. (for example, if you put a control inside a grid, it would be nice for the control to have a Row property -- they pseudo did this with attached properties.
It works something like: (note this probably doesn't precisely match WPF's implementation, and I'm leaving out the dependency property registration, as you aren't using XAML)
public class MoveBehavior: Behavior
{
private static Dictionary<Mob, int> MovementRateProperty;
public static void SetMovementRate(Mob theMob, int theRate)
{
MovementRateProperty[theMob] = theRate;
}
public static int GetMovementRate(Mob theMob)
{
// note, you will need handling for cases where it doesn't exist, etc
return MovementRateProperty[theMob];
}
}
The thing here is that the Behavior owns the property, but you don't have to go spelunking to get it Here's some code that retrieves a mob's movement rate:
// retrieve the rate for a given mob
int rate = MoveBehavior.GetMovementRate(theMob);
// set the rate for a given mob
MoveBehavior.SetMovementRate(mob, 5);
If it is related to the behavior, and only makes sense in the context of that behavior, then it should be stored as part of it.
A movement rate only makes sense for something that can move. Which means it should be stored as part of the object that represents its ability to move, which seems to be your MoveBehavior.
If that makes it too hard to access, it sounds more like a problem with your design. Then the question is not "should I cheat, and place some of the variables inside the Mob class instead of the behavior it belongs to", but rather "how do I make it easier to interact with these individual behaviors".
I can think of several ways to implement this. The obvious is a simple member function on the Mob class which allows you to select individual behaviors, something like this:
class Mob {
private List<Behavior> behaviors;
public T Get<T>(); // try to find the requested behavior type, and return it if it exists
}
Others can then do something like this:
Mob m;
MovementBehavior b = m.Get<MovementBehavior();
if (b != null) {
b.SetMovementRate(1.20f);
}
You might also place some of this outside the Mob class, creating a helper function which modifies the movement rate if it exists, and does nothing otherwise:
static class MovementHelper {
public static SetMovementRate(Mob m, float movementrate){
MovementBehavior b = m.Get<MovementBehavior();
if (b != null) {
b.SetMovementRate(1.20f);
}
}
}
and then others could use it like this:
MovementHelper.SetMovementRate(m, 1.20f);
which would provide easy access to modifying the behavior, but without cluttering up the Mob class. (Of course, it'd be tempting to turn this into an extension method, but that might lead to too much assorted clutter in the Mob class' public interface. It may be preferable to make it clear that this is helper functionality that resides outside the Mob class itself)
Take a look at component systems/entity systems design:
http://www.devmaster.net/articles/oo-game-design/
By far the best I've seen till now.
Smart people say it's the only way to go with larger games, but it requires a shift in how you think about OOP.
So what are you trying to do?
What's the simplest way for you to store the movement rate data?
If it is only needed in the MoveBehavior class then it should be in there:
public class MoveBehavior {
public int MovementRate { get; set; }
}
If it is needed inherently by the Mob class then it will be easier exposed through the Mob class:
public class Mob {
public int MovementRate { get; set; }
}
public class MoveBehavior {
public MoveBehavior(Mob mob) { MobInEffect = mob; }
public Mob MobInEffect {get; set;}
// can access MovementRate through MovInEffect.MovementRate
}
So it all depends on what you're trying to achieve with this behavior logic. I'd recommend you push the design decision until you really need to do it one way or another. Concentrate on doing it simple first and refactor later. Usually more often than not, doing early design guesswork can lead to overcomplicated architecture.
A more pragmatic solution…
What I mean is that you implement whatever you wanted from movement the in the Mob class first:
public class Mob {
// Constructors and stuff here
public void Move(long ticks)
{
// do some voodoo magic with movement and MovementRate here
}
protected int MovementRate { get; set; }
}
And when that works, rip out that implementation to a MoveBehavior class if you really need to:
public class Mob {
// Constructors and stuff here
public MoveBehavior Moving { set; get; }
public void Move(long ticks)
{
Moving.Move(ticks, this);
}
}
public class MoveBehavior {
protected int MovementRate { get; set; }
public void Move(long ticks, Mob mob)
{
// logic moved over here now
}
}
After that if you really need to do more than one type of behavior but they share a common interface then create that interface by then and let the behaviors implement that.
Edit: The below answer only really makes sense if you're not instancing a new MovingBehavior for every mob, but just have a singleton MovingBehavior.
I'd say that the mob (ugh, I hate that word for game NPCs, but it's not your fault) should, when addBehavior() is called, get a BehaviorState object that's returned from addBehavior() and that it keeps around, and is keyed to the behavior added. Then provide an interface for MovingBehavior to easily retrieve its BehaviorState object from movingMob, and it stores whatever it needs to store there.
If i was designing something like this i would try out using interfaces to define which behaviors a mob has:
public interface IMovable
{
int MovementRate { get; set; }
void MoveTo(int x, int y);
}
public class Monster : Mob, IMovable
{
public int MovementRate { get; set; }
public void MoveTo(int x, int y)
{
// ...
}
}
This way you can check if a mob can move by doing something like this:
Monster m = new Monster();
if (m is IMovable)
{
m.MoveTo(someX, someY);
}
IMHO, the movement rate is associated with the movingBehavior rather than with a Mob itself, and as you said, it doesn't necessarily move. So the variable should be associated with the behavior, a change in the movementRate is a change to his Behavior, not to the mob himself.
You could also create a base Mob class, and derive a MovingMob one. But I guess, this doesn't really apply, once apparently you can have an arbitrary combination of different behaviors...
-- EDIT --
First, apparently you won't have the same type of behavior twice in the same Mob (like, no mob has two movementBehaviors at the same type), so a set is a better option in this case, as it avoids duplicates
You could have a method in each mob like
public Behavior GetBehavior(Type type)
{
foreach (var behavior in behaviorHashSet)
{
if ( behavior.GetType() == type)
return behavior;
}
return null;
}
Then you could do whatever you want with this behavior once you have a Mob. Also, you could change the GetHashCode() and Equals() method to ensure you have no duplicate, or make the GetBehavior method even faster (constant time)