I have a feeling I'm doing this wrong. I'm new to abstract classes and such and have been reading tutorials for a little bit, but I can't figure out how to apply it to my situation. I think that my design might be faulty but I can't think of another way to do it. My company makes a few different computers and I need to be able to monitor the battery information. Although getting the information is not the problem, figuring out how to send the different commands to the base class to do what i need it to do. Say I want to get my cell 1 voltage. On one unit the command is 0x0418, on another it is 0x453. So in my information class I run a test to see what the model is. I have a Base class called battery that has a bunch of variables that are standard for each battery (cell voltage, charge ic, charging current etc etc) I then decided it would be good to make individual classes for each of my units that extends Battery.
Now my design of the classes I think is spot on (could be wrong as I am not good at abstraction and polymorphism). I have a panel that in the end would display the information that I get from the BatteryInformation class. something like Battery1Cell1Label.Text = batteryInfo.GetCell1(1); Battery2Cell1Label = batteryInfo.GetCell1(2).
So in my base class I guess I need a GetValue(byte command) (since it is a Embedded controller command to get each different types of information.) Maybe i should stop talking and just post my code of what i have and tell you the error that I have.
battery.cs
public abstract class Battery<T> //not sure that the <T> is right
{
public string Information { get; private set; }
public float Cell1 { get; private set; }
public float Cell2 { get; private set; }
public float Cell3 { get; private set; }
public float Cell4 { get; private set; }
public int FCC { get; private set; }
public bool ChargeIC { get; private set; }
public int StartCharge { get; private set; }
public int CurrentCharge { get; private set; }
public bool Exists { get; private set; }
protected internal void GetValue(byte command)
{
//Use Embedded controller to get said value
//ECPort.ReadEC(command);
//Testing Purposeses
Console.WriteLine(command);
}
}
Battery8800.cs
class Battery8800 : Battery<Battery8800>
{
public Battery8800() : base()
{
}
public void GetValue(BatteryCommands command)
{
base.GetValue((byte)command);
}
public enum BatteryCommands
{
Battery1VoltageHigh = 0x0402,
Battery1VoltageLow = 0x0403,
Batt1ChargeCurrentHigh = 0x0404,
Batt1ChargeCurrentLow = 0x0405,
Battery1MaxError = 0x0407,
Battery1RSOC = 0x0409,
Battery1FCCHigh = 0x040E,
Battery1FCCLow = 0x040F,
Battery1DCHigh = 0x0412,
Battery1DCLow = 0x0413,
Battery1Cell1High = 0x0418,
Battery1Cell1Low = 0x0419,
Battery1Cell2High = 0x041A,
Battery1Cell2Low = 0x041B,
Battery1Cell3High = 0x041C,
Battery1Cell3Low = 0x041D,
Battery1Cell4High = 0x041E,
Battery1Cell4Low = 0x041F,
PowerSource1 = 0x0420,
//many more commands for battery 2 etc etc
}
}
BatteryInformation.cs
class BatteryInformation
{
public Battery battery1; //error says it needs 1 type of argument
public Battery battery2; //error says it needs 1 type of argument
public BatteryInformation()
{
switch (UnitModel.GetModelEnum())
{
case UnitModel.DLIModel.DLI8300M:
battery1 = new Battery8300();
battery2 = new Battery8300();
break;
case UnitModel.DLIModel.DLI8400:
battery1 = new Battery8400();
battery2 = new Battery8400();
break;
case UnitModel.DLIModel.DLI8500:
battery1 = new Battery8500();
break;
case UnitModel.DLIModel.DLI8500P:
battery1 = new Battery8500P();
break;
case UnitModel.DLIModel.DLI8800:
battery1 = new Battery8800();
break;
case UnitModel.DLIModel.DLI9200:
battery1 = new Battery9200();
break;
default:
break;
}
//for testing purposes
battery1 = new Battery8800();
battery1.DoThis(Battery8800.BatteryCommands.Batt1ChargeCurrentHigh);
}
}
YEAH FOR DRAFT SAVING!!! the power just went out, and I didn't loose but 1 sentence!
so while my computer was turning back on I was thinking it might be better to do something like this in my battery panel class.
//in my timer_tick event
BatteryInformation.UpdateBatteries();
battery1Cell1Label.Text = BatteryInformation.Battery1.Cell1.ToString();
//etc etc
but i still need to get this working but am having a hard time figuring out how to do abstraction. Thank you for your time.
EDIT
I think i'm going about this the wrong way.
class Battery1_8400 : Battery
{
public override bool Update()
{
//TODO finish
Exists = GetValue((ushort)Commands.PowerSource) != 0xFF;
if (Exists)
{
Cell1 = GetValue((ushort)Commands.Cell1Low, (ushort)Commands.Cell1High) / 1000.0f;
Cell2 = GetValue((ushort)Commands.Cell2Low, (ushort)Commands.Cell2High) / 1000.0f;
Cell3 = GetValue((ushort)Commands.Cell3Low, (ushort)Commands.Cell3High) / 1000.0f;
FCC = GetValue((ushort)Commands.FCCLow, (ushort)Commands.FCCHigh);
Voltage = GetValue((ushort)Commands.VoltageLow, (ushort)Commands.VoltageHigh);
return true;
}
else
{
return false;
}
}
private enum Commands
{
PowerSource = 0x0480,
Charge = 0x0432,
RSOC = 0x0734,
DCLow = 0x0402,
DCHigh = 0x0403,
FCCLow = 0x0404,
FCCHigh = 0x0405,
MaxError = 0x0730,
Cell1Low = 0x0778,
Cell1High = 0x0779,
Cell2Low = 0x077C,
Cell2High = 0x077D,
Cell3Low = 0x0780,
Cell3High = 0x0781,
VoltageLow = 0x0438,
VoltageHigh = 0x0439,
ChargeCurrentLow = 0x0728,
ChargeCurrentHigh = 0x0729,
ChargeIC = 0x1A03,
}
}
I have 9 files that are ALL identical in terms of how the Update command works the difference is in the enum. The commands are slightly different per class. look at batter2_8400.cs 's enum
private enum Commands
{
PowerSource = 0x0480,
Charge = 0x04C2,
RSOC = 0x0834,
DCLow = 0x0492,
DCHigh = 0x0493,
FCCLow = 0x0494,
FCCHigh = 0x0495,
MaxError = 0x0830,
Cell1Low = 0x0878,
Cell1High = 0x0879,
Cell2Low = 0x087C,
Cell2High = 0x087D,
Cell3Low = 0x0880,
Cell3High = 0x0881,
VoltageLow = 0x04C8,
VoltageHigh = 0x04C9,
ChargeCurrentLow = 0x0828,
ChargeCurrentHigh = 0x0829,
ChargeIC = 0x1A04,
}
the update command is identical in that one as well as the other 7 files. Seems kinda bad design to me, but i'm stumped as to how I should do this. By the way this is what my classes look like after the one answer I was given and the few comments that was received.
your base class BatteryInformation should have abstract properties for each value you need to retrieve like so:
public abstract class BatteryInfo {
// int should be replaced with the actual data type of the value
public abstract int VoltageHigh { get; }
public abstract int VoltageLow { get; }
// etc. for each value you need
}
Then in your child class you implement each property
public class Battery8800 : BatteryInfo {
public override int VoltageHigh {
get {
int value;
// do code to retrieve value
return value;
}
}
}
In addition, I would provide a method somewhere that your UI can consume that looks like the following:
public IEnumerable<BatteryInfo> GetAllBatteryInfo() {
// get each battery
}
That way the UI does not need to worry about how the battery info is retrieved for each battery. That allows you to use one of the list or grid style controls to view the battery info.
In the end I think i figured out what I should do. It looks clean to me and seems to make sense. Maybe you can critique it?
public abstract class Battery
{
public string Information { get; set; }
public float Cell1 { get {return GetValue(Cell1Low, Cell1High) / 1000.0f;} }
public float Cell2 { get {return GetValue(Cell2Low, Cell2High) / 1000.0f;} }
public float Cell3 { get {return GetValue(Cell3Low, Cell3High) / 1000.0f;} }
public float Cell4 { get {return GetValue(Cell4Low, Cell4High) / 1000.0f;} }
public float Voltage { get {return GetValue(VoltageLow, VoltageHigh);} }
public int DC { get {return GetValue(DCLow, DCHigh);} }
public int FCC { get {return GetValue(FCCLow, FCCHigh);} }
//public bool ChargeIC { get {return } }
//public int StartCharge { get {return } }
//public int CurrentCharge { get {return } }
public bool Exists { get {return GetValue(PowerSource) != 0xFF} }
public int FCCPercent { get {return ((FCC * 100) / DC);} }
/// <summary>
/// Gets a value depending on the Embedded controller
/// </summary>
/// <param name="low">The low byte command to process</param>
/// <param name="high">The high byte command to process</param>
/// <returns></returns>
private int GetValue(ushort low, ushort high)
{
//Use Embedded controller to get said value
//ECPort.ReadEC(command);
//Testing Purposeses
var lowValue = ECPort.ReadEC(low);
var highValue = ECPort.ReadEC(high);
return (int)((highValue << 8) + lowValue);
}
private int GetValue(ushort command)
{
return (int)ECPort.ReadEC(command);
}
public abstract ushort PowerSource {get;}
public abstract ushort Charge{get;}
public abstract ushort RSOC{get;}
public abstract ushort DCLow{get;}
public abstract ushort DCHigh{get;}
public abstract ushort FCCLow{get;}
public abstract ushort FCCHigh{get;}
public abstract ushort MaxError{get;}
public abstract ushort Cell1Low{get;}
public abstract ushort Cell1High{get;}
public abstract ushort Cell2Low{get;}
public abstract ushort Cell2High{get;}
public abstract ushort Cell3Low{get;}
public abstract ushort Cell3High{get;}
public abstract ushort Cell4Low { get; }
public abstract ushort Cell4High { get; }
public abstract ushort VoltageLow{get;}
public abstract ushort VoltageHigh{get;}
public abstract ushort ChargeCurrentLow{get;}
public abstract ushort ChargeCurrentHigh{get;}
public abstract ushort ChargeIC{get;}
}
then on my sub classes that inherit it an example would be this
class Battery1_8400 : Battery
{
public override ushort PowerSource { get {return 0x0480;}}
public override ushort Charge { get {return 0x0432;}}
public override ushort RSOC { get {return 0x0734;}}
public override ushort DCLow { get {return 0x0402;}}
public override ushort DCHigh { get {return 0x0403;}}
public override ushort FCCLow { get {return 0x0404;}}
public override ushort FCCHigh { get {return 0x0405;}}
public override ushort MaxError { get {return 0x0730;}}
public override ushort Cell1Low { get {return 0x0778;}}
public override ushort Cell1High { get {return 0x0779;}}
public override ushort Cell2Low { get {return 0x077C;}}
public override ushort Cell2High { get {return 0x077D;}}
public override ushort Cell3Low { get {return 0x0780;}}
public override ushort Cell3High { get {return 0x0781;}}
public override ushort VoltageLow { get {return 0x0438;}}
public override ushort VoltageHigh { get {return 0x0439;}}
public override ushort ChargeCurrentLow { get {return 0x0728;}}
public override ushort ChargeCurrentHigh { get {return 0x0729;}}
public override ushort ChargeIC { get {return 0x1A03;}}
}
now all i have to do is edit the one file battery.cs if i need to make a change to it.
Related
I'm currently working on project (for fun) that involves simulating logic gates. I have a Connection.cs and a Gate.cs that is the parent of other classes like Not, And, Or, etc. In my Gate class I have an abstract method Evaluate that will end up doing the work with inputs and setting outputs.
public abstract class Gate : IConnectable {
private int[] inputs;
private int[] outputs;
protected Gate(int inputCount, int outputCount) {
inputs = new int[inputCount];
outputs = new int[outputCount];
}
...
public abstract void Evaluate();
}
public class Connection {
private IConnectable input;
private IConnectable output;
public Connection(IConnectable from, IConnectable to) {
input = from;
output = to;
}
}
In the end, I am trying to figure out a concise way to have a Gate object contain references to its connections that are inputs/outputs and to have the Connections know what is on either end of the "wire". Is there an easy way to do this?
Generally you want some way to represent a graph. There are many ways to do that.
I would consider a design like this as a starting point:
interface IGate
{
bool Value { get; }
}
class And : IGate
{
public IGate X { get; private set; }
public IGate Y { get; private set; }
public bool Value
{
get
{
return X.Value && Y.Value;
}
}
public And(IGate x, IGate y)
{
X = x;
Y = y;
}
}
class Input : IGate
{
public bool Value { get; set; }
public Input(bool value)
{
Value = value;
}
}
An example is:
new And(new Input(true), new And(new Input(true), new Input(false))).Value
I usually do something like this
public class Node {
private static List<Node> nodes = new List<Node>();
private List<Node> inputs { get; set;}
private List<Node> outputs {get;set;}
protected Node() { }
protected Node(Node input, Node outPut) {
Node newNode = new Node();
nodes.Add(newNode);
newNode.inputs.Add(input);
newNode.outputs.Add(output);
}
}
I want to create configuration for my application using static classes.
Firstly please forgive my ignorance, I'm not a full time c# dev. I come from a Ruby/Javascript world where dynamic access to constants & variables is trivial.
Whether or not this is the right approach here I'm not 100% at the moment. Would be greatful of other suggested approaches.
I have the following static class setup for my config:
public static class Config
{
public static class MaterialQuality
{
public static class Low
{
public const float Value = 0.1f;
public const int Cost = 10;
}
public static class Medium
{
public const float Value = 0.2f;
public const int Cost = 20;
}
public static class High
{
public const float Value = 0.2f;
public const int Cost = 40;
}
}
}
I then have a class Material, which is passed an enum value relating to the aboves types Low,Medium,High.
The reason for the enum in unity this gives a quick way for devs to provide level designers with an option list for a an object.
So by choosing an enum value the level designer can set the properties stored in the config without actually having to enter the values directly onto the object. The values are set against the object when it is initialised.
In the constructor I want to set member variables for Cost & Value from the static config values for the MaterialQuality enum value passed.
public enum MaterialQuality
{
Low,Medium,High
}
public class Material
{
private int Cost;
private float Value;
Material(MaterialQuality quality) {
Cost = Config.MaterialQuality.<quality>.Cost;
Value = Config.MaterialQuality.<quality>.Value;
//in Javascript I'd use associative array access to the object
Cost = Config.MaterialQuality[quality].Cost;
//in Ruby we have const_get() on classes.
Cost = Config.MaterialQuality.const_get(quality).Cost
}
}
The main reason for this approach is to provide single place for configuration & provide a fairly simple way for a non technical person to make changes to parts of the application without having to delve into the main classes. Also it allows me to take advantage of the constants being available in intellisense.
I'm a fan of using dictionaries for this type of configuration.
void Main()
{
var config = Config.Qualities[MaterialQualities.Low];
var cost = config.Cost;
var value = config.Value;
}
public static class Config
{
public static Dictionary<MaterialQualities, MaterialQuality> Qualities =
new Dictionary<MaterialQualities, MaterialQuality>
{
{ MaterialQualities.Low, new MaterialQuality { Value = 0.1F, Cost = 10 }},
{ MaterialQualities.Medium, new MaterialQuality { Value = 0.2F, Cost = 20 }},
{ MaterialQualities.High, new MaterialQuality { Value = 0.2F, Cost = 40 }},
};
}
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
public enum MaterialQualities
{
Low, Medium, High
}
Probably better approach would be:
public static class Config
{
public class Material
{
public Material(float value, int cost){
Value = value;
Cost = cost;
}
public float Value {get; private set;}
public int Cost {get; private set;}
public Material GetFor(MaterialQuality quality){
switch(quality){
case MaterialQuality.Low: return new Material(0.1f, 10);
case MaterialQuality.Medium: return new Material(0.2f, 20);
case MaterialQuality.High: return new Material(0.2f, 40);
}
throw new Exception("Unknown material quality " + quality);
}
}
}
and later you can use that:
//....
Material materialData = Material.GetFor(quality);
Cost = materialData.Cost;
Value = materialData.Value;
//...
I would use a struct and static properties in MaterialQuantity instead of an enum. Something like the following:
public struct MaterialQualityInfo
{
public MaterialQualityInfo( float value, int cost )
{
Value = value;
Cost = cost;
}
public float Value { get; private set; }
public int Cost { get; private set; }
}
public static class Config
{
public static class MaterialQuality
{
public static MaterialQualityInfo Low
{
get { return new MaterialQualityInfo( 0.1f, 10 ); }
}
public static MaterialQualityInfo Medium
{
get { return new MaterialQualityInfo( 0.2f, 20 ); }
}
public static MaterialQualityInfo High
{
get { return new MaterialQualityInfo( 0.2f, 40 ); }
}
}
}
public class Material
{
private int Cost;
private float Value;
Material( MaterialQualityInfo quality )
{
Cost = quality.Cost;
Value = quality.Value;
}
}
IMHO, this isn't a good usage of static classes. You should use regular object-oriented programming to solve the issue.
I see that all material qualities have 2 properties in common: Value and Cost. For me, this means that you should design a class called MaterialQuality:
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
If material qualities are part of an application configuration, I see that you should design a Configuration class as follows:
public class Configuration
{
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
...and if you want to initialize a configuration per application life-cycle, you can improve Configuration class using static field initializers:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
public static Configuration Current => _current;
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
Now adding new material qualities to current configuration is as easy as the following code:
Configuration.Current.MaterialQualities.Add(new MaterialQualities { Value = 0.1f, Cost = 10 });
If you want to provide a fluent API to add material qualities is also easy: we're going to turn public MaterialQualities properties into an ImmutableList<T> (so you force developers to add materials using the method to do so) and add an AddMaterial method:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
private readonly List<MaterialQuality> _materialQualities = new List<MaterialQuality>();
public static Configuration Current => _current;
public IImmutableList<MaterialQuality> MaterialQualities => _materialQualities.ToImmutableList();
public Configuration AddMaterial(float value, int cost)
{
_materialQualities.Add(new MaterialQuality { Value = value, Cost = cost });
return this;
}
}
...and now adding many materials would look even nicer!
Configuration.Current.AddMaterial(0.1f, 10)
.AddMaterial(0.2f, 20)
.AddMaterial(0.2f, 40);
How about:
public enum MaterialQuality
{
Low, Medium, High
}
public class Material
{
private int Cost;
private float Value;
private readonly Dictionary<MaterialQuality, Tuple<int, float>> storageMap = new Dictionary<MaterialQuality, Tuple<int, float>>
{
{ MaterialQuality.Low, Tuple.Create(10, 0.1f)},
{ MaterialQuality.Low, Tuple.Create(20, 0.2f)},
{ MaterialQuality.Low, Tuple.Create(40, 0.2f)},
};
public Material(MaterialQuality quality)
{
Cost = storageMap[quality].Item1;
Value = storageMap[quality].Item2;
}
}
If you are not using your enum widely, you could do something like:
public class Material
{
public float Value { get; private set; }
public int Cost { get; private set; }
public Material(float value, int cost)
{
Value = value;
Cost = cost;
}
public static Material Low { get { return new Material(0.1f, 10); } }
public static Material Medium { get { return new Material(0.2f, 20); } }
public static Material High { get { return new Material(0.2f, 40); } }
}
And then:
var myLowMaterial = Material.Low;
var myMediumMaterial = Material.Medium;
var myHighMaterial = Material.High;
Unless you are using your enum for something, in which case you could add:
public static Material Get(MaterialQuality quality)
{
switch(quality)
{
case MaterialQuality.Low:
return Low;
case MaterialQuality.Medium:
return Medium;
case MaterialQuality.High:
return High;
}
throw new Exception("We should never go here");
}
I have a class Father and an inherited class Child. Inside the Child's constructor I want to pass a Father class to cast all Father's properties.
This is my code
class Father
{
int prop1;
int prop2;
// many more properties;
}
class Child : Father
{
string _name;
int _age;
//etc...
public Child(string Name, int Age, Father father)
{
this._name = Name;
this._age = Age;
base = father; //<== this is what I mean to do
}
I know I can't do this directly. What is the right way?
This is complete code, some code is in spanish
class AuditRegistry : Audit
{
protected string _cud;
protected int _employee, _consecutive;
protected DateTime _date;
public string CUD { get { return _cud; } }
private int Consecutive { get { return _consecutive; } }
public DateTime Date { get { return _date; } }
public int Client { get; set; }
public int Employee { get { return _employee; } }
public float NetAmount
{
get
{
float acum = 0;
//Sum (qty * price) of products in a struct collection
}
}
public float GrossAmount
{
get
{
float acum = 0;
//Sum in acum (qty * price + tax) of each products in a struct collection
return acum;
}
}
public float Paid
{
get
{
float acum = 0;
//Sum every paid in a struct collection
return acum;
}
}
public float Change
{ get; set; }
public bool FullPaid
{
get { return (Paid != null && Paid >= NetAmount); }
}
public ArticlesCollection Products { get; set; } //struct previusly declared
public PaidsCollection Paids { get; set; } // struct previously declared
public AuditRegistry(string CUD, int Employee, int Consecutive, DateTime Date, int Client, int C, int Company, int Terminal )
{
this._cud = CUD;
this._employee = Employee;
this._consecutive = Consecutive;
this._date = Date;
this.Client = Client;
base._c = C;
base._company = Company;
base._terminal = Terminal;
}
}
class Order : AuditRegistry
{
int _consec;
public DateTime DeliveryDate { get; set; }
public int Consecutive { get { return _consec; } }
public char Modification { get; set; }
public string Code { get { return (_consec.ToString() + Modificacion); } }
public bool Entregado { get; set; }
/// <summary>
/// Constructor for load a Order from database to memory
/// </summary>
public Order(DateTime DeliveryDate, int Consecutive, char Modification, AuditRegistry Registry) // Here is the child constructor
{
this.DeliveryDate = DeliveryDate;
this._consec = Consecutive;
this.Modification = Modification;
base = AuditRegistry; //Wrong idea
}
/// <summary>
/// Constructor for new Order
/// </summary>
public Pedido(DateTime DeliveryDate, int Employee)
{
this.DeliveryDate = DeliveryDate;
this._consec = 1;
this.Modification = 'A';
base._employee = Employee;
base._date = DateTime.Now;
}
}
Semantics of a child being a father aside...
A good way is using a copy constructor:
class Father
{
int prop1;
int prop2;
// much more properties;
protected Father(Father copy)
{
prop1 = copy.prop1;
prop2 = copy.prop2;
}
}
class Child : Father
{
string _name;
int _age;
//etc...
public Child(string Name, int Age, Father father)
: base(father)
{
this._name = Name;
this._age = Age;
}
}
Its a protected constructor so only children of the parent class can call it. You use the constructor chaining base(father) to intantiate the construtor of the base class and pass the object you want to copy.
You can't assign the base object directly in code, its just a reference to the instance of the base class that the current class derives from.
There is absolutely no way to do this. A Child is a Father and you can't just swap part of the object out to another reference. The base keyword is only intended for calling base class methods explicitly.
Given that a Child is not a "type of" Father, inheritance is probably the wrong answer here anyways. You would be better off doing something like:
class Person
class Father : Person
class Child : Person
{
Father father;
}
(Pseudo-code above). Basically, prefer composition over inheritance here.
I've been working on building several classes which inherit from one base class but I'm not entirely confident on how inheritance and polymorphism work in C# at this stage.
My base class looks like this:
abstract class Structure
{
public int currentCost = 0;
public int currentArea = 0;
public int currentPopulation = 0;
public int currentConstruction = 0;
public int currentEnergy = 0;
public int currentEconomy = 0;
public abstract int baseCost { get; }
public abstract int baseEnergy { get; }
public abstract int baseEconomy { get; }
public abstract int baseConstruction { get; }
public int baseArea = -1;
public int basePopulation = -1;
public int level = 0;
public abstract string structureName { get; }
}
Now, classes that inherit from the Structure class will be made to provide their own assignments for the abstract variables which is fine as most of the classes vary wildly in the figures they assign.
The abstract variables are used in the derived classes in the following (incomplete) manner:
class BiosphereModification : Structure
{
const int baseEconomyBiosphereModification = 0;
const int baseConstructionBiosphereModification = 0;
const int baseCostBiosphereModification = 2000;
const int baseEnergyBiosphereModification = 0;
const int baseFertilityBiosphereModification = 1;
const string structureNameBiosphereModification = "BiosphereModification";
public override int baseCost { get { return baseCostBiosphereModification; } }
public override int baseEconomy { get { return baseEconomyBiosphereModification; } }
public override int baseEnergy { get { return baseEnergyBiosphereModification; } }
public override int baseConstruction { get { return baseConstructionBiosphereModification; } }
}
However, the non-abstract variables will be the same across the majority of derived classes, but not all of them.
I could make them all abstract and force each class to provide it's own value, but this seems counter-intuitive. What I would prefer is a way to provide a value in the base class and provide an override in a derived class if needed.
Is there a way to do this? I know that this can be done with methods declared virtual. This allows the derived class to use the base classes method unless it provides one of it's own. Surely a similar thing exists for this?
What I would prefer is a way to provide a value in the base class and provide an override in a derived class if needed.
Properties can be declared virtual, as well:
public virtual int BaseCost { get { return 0; } }
public virtual int BaseEnergy { get { return 42; } }
public virtual int BaseEconomy { get { return 3982; } }
public virtual int BaseConstruction { get { return 398829; } }
You can then override them when appropriate:
public override int BaseCost { get { return 2; } }
I'm wondering about what's the way to go, if I need to publicate data-interfaces but want to use them internal with extended calculated properties. To make it clearer:
// The public interface
public interface IData
{
int Property { get; }
}
// The internal interface
internal interface IExtendedData : IData
{
int ExtendedProperty { get; }
}
// The assumed implementation of someone using my interface
public class Data : IData
{
public Data(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public override string ToString()
{
return Property.ToString();
}
}
// My implementation
internal class ExtendedData : IExtendedData
{
public ExtendedData(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
public override string ToString()
{
return Property.ToString() + ExtendedProperty.ToString();
}
}
// publicated by me, for the person who uses my dll
public static class Calculations
{
public static int DoSomeCalculation(IData data, int parameter)
{
// This probably don't work, but maybe shows what I want to do
IExtendedData tempData = (ExtendedData)data;
return tempData.ExtendedProperty * parameter;
}
}
I'm realy frustrated, cause I feel like missing some basical programing skills.
You could solve this problem by implementing ExtendedData as a Wrapper for a class implementing IData
internal class ExtendedData : IExtendedData
{
private IData data;
public ExtendedData(IData data)
{
this.data = data;
}
public int Property
{
get { return data.Property; }
private set { data.Property = value; }
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
}
and use this in DoSomeCalculation like
IExtendedData tempData = new ExtendedData(data);
ExtendedData could inherit from Data:
class ExtendedData : Data
{...}
And for creation of a Data object you add a factory like so:
public class DataFactory
{
public IData CreateData()
{
return new ExtendedData();
}
}
User have to create all its Data objects by this factory. You can ensure it by making Data's constructor internal.
In your DLL you can then cast to ExtendedData.