My goal is to create a type 'GameState' that has a set amount of different states.
I want it to act almost exactly like an enum set but I want there to be more than a single integer as data.
As an example, this is what I want to do:
switch(this.gameState)
{
case(Wait):
if(elapsedTime > gameState.TimeOutTime)
//do stuff
break;
case(Play):
if(elapsedTime > gameState.TimeOutTime)
//do other stuff
break;
}
So instead of GameState just being an enumeration of integers, I want it to contain variables like TimeOutTime and other useful information about that GameState.
Is there a way of adding depth to an enumeration or am I just attacking this problem at the wrong angle?
There are already good answers (#Selman22, #Max).
But I guess they are missing an important info: You should not switch on type. Use polymorphism instead.
So, based on your example, you should use something like this:
public abstract class GameState
{
public int TimeOutTime { get; set; }
public void CheckDoStuff()
{
if (elapsedTime > gameState.TimeOutTime) DoStuff();
}
protected abstract void DoStuff();
}
public WaitState : GameState
{
protected override DoStuff()
{
// Do stuff (wait)
}
}
public PlayState : GameState
{
protected override DoStuff()
{
// Do other stuff (play)
}
}
Note: I didn't add any enum, because I don't think one is really needed in this case.
What you want is a class. You can't do that with enums, instead add a class and make the enum a property of your class.
class GameState
{
public GameStateEnum State { get; set; }
public int TimeOutTime { get; set; }
// other properties...
}
You could easliy create a class for that like:
public class GameState
{
public StateEnum State {get; set;}
public DateTime TimeOutTime {get; set;}
}
Creating a list of GameStates would be easy like:
List<GameState> gameStateList = new List<GameState>();
You can't do that with .NET enums (you can with Java though)
Assuming you elapsedTime is a DateTime, something like:
using System;
public class GameState
{
private readonly TimeOutTime _timeOutTime;
public GameState(TimeOutTime timeOutTime)
{
_timeOutTime = timeOutTime;
}
public TimeOutTime TimeOutTime { get { return _timeOutTime; } }
}
public class TimeOutTime
{
private readonly DateTime _dateTime;
public TimeOutTime(DateTime dateTime)
{
_dateTime = dateTime;
}
public static implicit operator DateTime(TimeOutTime timeOutTime)
{
return new TimeOutTime(timeOutTime);
}
public static implicit operator TimeOutTime(DateTime timeOutTime)
{
return new TimeOutTime(timeOutTime);
}
}
Related
I wrote the code below and i want to access the private varibale in another class, i created instance of the class and tried to access it but couldn't. can someone point out what I did wrong in the code below?
using System;
namespace lab_first
{
public class AccessModifiers
{
private int Abc { get; set; }
private int bcd { get; set; }
}
class Program
{
static void Main(string[] args)
{
var acc = new AccessModifiers();
Console.WriteLine(acc.Abc)
}
}
}
You make members private so that nobody outside the class can access them.
This goes inline with the principle of information hiding.
Your example should look like this:
public class AccessModifiers
{
// You can only access this inside of the class AccessModifiers
private int Abc { get; set; }
internal void SetValue(int x){
// Access possible, because SetValue() is inside the same class
Abc = x;
}
internal int GetValue(){
// Access possible, because GetValue() is inside the same class
return Abc;
}
}
class Program
{
static void Main(string[] args)
{
var acc = new AccessModifiers();
// Abc is never modified directly, only indirectly.
acc.SetValue(5);
Console.WriteLine(acc.GetValue());
}
}
However, there is still a way to access the private member. It's called Reflection. However, note that private variables are considered an implementation detail and might change at any time, so you can't rely on it. E.g. someone might change the name from Abc to def and your Reflection-based approach fails.
You can either change private to internal or public in this case.
Another way is declaring the variables in the class as private and using C# Properties in the class to set and get the values of variables. this is called encapsulation which is a protective shield that prevents the data from being accessed by the code outside this shield).
public class AccessModifiers
{
private int _abc { get; set; }
private int _bcd { get; set; }
public int Abc
{
get
{
return _abc;
}
set
{
_abc = value;
}
}
public int Bcd
{
get
{
return _bcd;
}
set
{
_bcd = value;
}
}
}
Okay so I am working on a project that haves a abstract public abstract bool IsFull { get; } this is how the school wants me to set it up. I was trying to figure out a work around that but I can't. I have a few files not sure if I want them all to post. so in my class it is inherited from a different class. so when I initiate it from the program cs class I can't get the boolean to change with a simple IsFull = true. I tried IsFull.Equal(true); but read that just a comparison attribute. I will show my code. Remember this is 100% new to me so if you asked questions why don't i do it this way the answer is I never was taught that lol.
So is there a way I can override it within the sweettooth class?
My Ninja class
using System.Collections.Generic;
using IronNinja.Interfaces;
namespace IronNinja.Models
{
abstract class Ninja
{
protected int calorieIntake;
public List<IConsumable> ConsumptionHistory;
public Ninja()
{
calorieIntake = 0;
ConsumptionHistory = new List<IConsumable>();
}
public abstract bool IsFull { get; }
public abstract void Consume(IConsumable item);
}
}
my inherited class sweettooth
using IronNinja.Interfaces;
namespace IronNinja.Models
{
class SweetTooth : Ninja
{
public string Name;
public SweetTooth(string name)
{
Name = name;
}
public override bool IsFull { get; }
public override void Consume(IConsumable item)
{
// provide override for Consume
int sweet = 0;
if (calorieIntake >= 1500)
{
}
else
{
if (item.IsSweet)
{
sweet = 10;
}
ConsumptionHistory.Add(item);
calorieIntake += item.Calories + sweet;
}
item.GetInfo();
}
}
}
Lastly my Programs .cs file
using System;
using IronNinja.Models;
namespace IronNinja
{
class Program
{
static void Main(string[] args)
{
Buffet hungryJack = new Buffet();
SweetTooth Albert = new SweetTooth("Alby");
while (!Albert.IsFull)
{
Albert.Consume(hungryJack.Serve());
}
foreach (Food item in Albert.ConsumptionHistory)
{
Console.WriteLine(item.Name);
System.Console.WriteLine(item.GetInfo());
}
}
}
}
From my understanding, the IsFull property can simply provide the logic to return whether or not the SweetTooth is full:
public override bool IsFull => calorieIntake >= 1500;
And then in SweetTooth.Consume you would check if they are full before consuming more consumables:
public override void Consume(IConsumable item)
{
// provide override for Consume
int sweet = 0;
if (IsFull)
{
return;
}
else
{
if (item.IsSweet)
{
sweet = 10;
}
ConsumptionHistory.Add(item);
calorieIntake += item.Calories + sweet;
}
item.GetInfo();
}
You simply can't, by language design. You can't make your subclass "more permissive" than the parent class.
If you want to assign IsFull property, you have to do it into the SweetTooth class through the constructor. Generally if you set a property with private setter is because you want to manage its state internally and do not let the client code to handle it.
Then, change the SweetTooth constructor as per below:
public SweetTooth(string name, bool isFull)
{
Name = name;
IsFull = isFull;
}
The alternative is to add a private backing field, but again you can edit this only internally:
private bool _isFull;
public override bool IsFull => _isFull;
The Equal method compares two values. In your specific case you called bool.Equals(bool) overload which worked as Albert.IsFull == true
I am modelling a program that simulates driving and refueling cars and trucks. So this is what I have done so far:
public abstract class Vehicle
{
protected Vehicle(double fuelQuantity, double fuelConsumption)
{
this.FuelQuantity = fuelQuantity;
this.FuelConsumption = fuelConsumption;
}
public double FuelQuantity { get; protected set; }
public double FuelConsumption { get; protected set; }
public abstract string Drive(double distance);
public abstract void Refuel(double liters);
}
public class Car : Vehicle
{
public Car(double fuelQuantity, double fuelConsumption) : base (fuelQuantity, fuelConsumption)
{
}
public override string Drive(double distance)
{
}
public override void Refuel(double liters)
{
}
}
So, I want to increase the value of the fuel consumption of the cars with 0.9 liters (it's summer, so cars use air conditioners). Where this can be done? I don't want to do it in the constructor because I don't think it's okay.
This would be a good place to add a decorator.
Some pseudo code (not complete!) but hopefully you get the idea.
public class VehicleDecorator : Vehicle
public VehicleDecorator(Vehicle vehicle)
{
this.vehicle = vehicle;
}
public class VehicleWithAc : VehicleDecorator
public VehicleWithAc(Vehicle vehicle) : base(vehicle){}
public override double FuelConsumption {
get{
return base.FuelConsumption+0.9 } }
Then in your program, create your car and decorate it with a VehicleWithAc decorator
Program
var baseCar = new Car();
var summerDriver = new VehicleWithAc(baseCar)
I think the problem you have is that you're passing fuelConsumption as a single variable in to the constructor, thereby stating
This is the fuel consumption of the car, full stop.
As you've found out, working through the problem - fuel consumption isn't a static thing, it's dependant on other variables, such as whether the AC is on. Doug was getting close with his mention of the decorator, but I think it can be a little simpler, but more flexible.
I think you should still pass a fuel consumption figure in, and for simplicitys sake, we'll call it baseFuelConsumption. Remember, vehicles are usually graded on urban, and highway fuel consumptions as they are generally different, but for the purposes of this, we'll ignore it.
Leaving out distance travelled etc, we have:
public abstract class Vehicle
{
private readonly double _baseFuelConsumption;
protected double BaseFuelConsumption => _baseFuelConsumption;
protected Vehicle(double baseFuelConsumption) => _baseFuelConsumption = baseFuelConsumption;
public virtual double ActualFuelConsumption => BaseFuelConsumption;
}
So, how much extra fuel consumption does an AC use? Let's take Doug's answer as a base-point, and give that to our car....
public class Car : Vehicle
{
private const double _ACModifier = 0.9;
public Car()
:base(1)
{
}
public bool IsACOn { get; set; }
public override double ActualFuelConsumption
{
get
{
double consumption = base.ActualFuelConsumption;
consumption += IsACOn ? _ACModifier : 0;
return consumption;
}
}
}
Now, for the purposes of your simulation you can switch the AC on and off, over time, and measure the ActualFuelConsumption property over time.
If you want to use this stracture you have to set custom rules for properties.
public abstract class Vehicle
{
protected Vehicle(double fuelQuantity, double fuelConsumption)
{
this.FuelQuantity = fuelQuantity;
this._fuelConsumption = fuelConsumption;
this.FuelConsumption = fuelConsumption;
}
public double FuelQuantity { get; protected set; }
private double _fuelConsumption { get; set; }
public double FuelConsumption {
get { return _fuelConsumption; }
protected set {
_fuelConsumption = (_fuelConsumption + 0.9);
} }
public abstract string Drive(double distance);
public abstract void Refuel(double liters);
}
Because your class is abstract and you dont have no overridable in properties in your derived class you cant have access to base properties.You can use condition in set for example
public double FuelConsumption {
get { return _fuelConsumption; }
protected set {
if(Issummer)
{
_fuelConsumption = (_fuelConsumption + 0.9);
}else{ _fuelConsumption =_fuelConsumption;}
} }
I have something like this:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
public class Engine : Ship
{
public int engines() { return 5; }
public class Piston
{
public int pistons(){return 5;}
}
}
}
void Main
{
Ship ship = new Ship()
int a = ship.Engine.Piston.pistons;//why this not working?
}
I don't know what I'm doing wrong. Why isn't "ship.Engine.Piston.pistons" working?
Because Engine is type inside the Ship class, and its member.
To fix this can do something like:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
private void Engine _myEngine = new Engine(); //DEFINE ENGINE MEMBER
public Engine MyEngine { //DEFINE A PROPERTY TO ACCESS THAT MEMBER
get {
return _myEngine;
}
}
public class Engine : Ship
{
public int engines() { return 5; }
private Piston _myPiston = new Piston();//DEFINE PISTON MEMBER
public Piston MyPiston {//DEFINE A PROPERTY TO ACCESS THAT
get {
return _myPiston ;
}
}
public class Piston
{
public int pistons(){return 5;}
}
MEMBER
}
}
and after use it like:
int a = ship.MyEngine.MyPiston.pistons
You must initiate an object of your sub type (Nested type) in order to access its method, in your case you are not creating any object of your nested types so you can not access its methode.
While you create a new Ship() you are not creating any Engine or Piston, so you can not access the methode Pistons() of the non existing object.
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();
}
}