Here is only an example from my code. I'm looking for a good way to maintain my classes in order and following some OOP rules.
This my abstract class Problem:
public abstract class Problem<T> : IEquatable<T>
{
public abstract int ResultCount { get; }
protected abstract bool CheckTheAnswer(params object[] results);
public abstract bool Equals(T other);
}
Below is one class which derives from Problem, Arithetic class contains all the necessary that contains in a math problem, and how to resolve it:
public enum Operations
{
Addition, Subtraction, Multiplication, Division
}
public class Arithmetic : Problem<Arithmetic>
{
public decimal Number1
{
get;
set;
}
public Operations Operation
{
get;
set;
}
public decimal Number2
{
get;
set;
}
public override int ResultCount
{
get { return 1; }
}
protected override bool CheckTheAnswer(params object[] results)
{
if (results.Length != ResultCount)
throw new ArgumentException("Only expected " + ResultCount + " arguments.");
decimal result = (decimal)results[0];
switch (Operation)
{
case Operations.Addition:
return Number1 + Number2 == result;
case Operations.Subtraction:
return Number1 - Number2 == result;
case Operations.Multiplication:
return Number1 * Number2 == result;
case Operations.Division:
return Number1 / Number2 == result;
default:
throw new Exception("Operator unexpected");
}
}
public override bool Equals(Arithmetic other)
{
if (other == null)
return false;
return this.Number1 == other.Number1 && Number2 == other.Number2;
}
}
public class Addition : Arithmetic
{
public Addition(decimal addend1, decimal addend2)
: base()
{
Number1 = addend1;
Number2 = addend2;
Operation = Operations.Addition;
}
}
// Subtraction, Multiplication and Divison here
Then I have another class which generate an Arithmetic problem, it receives a Tuple where contains some properties that indicates the conditions
interface IProblemFactory<T> where T : Problem<T>
{
T Create();
}
public class ArithmeticProblemFactory : IProblemFactory<Arithmetic>
{
private Tuple<Operations, Range, Range> _condition;
public ArithmeticProblemFactory(Tuple<Operations, Range, Range> condition)
{
this._condition = condition;
}
public Arithmetic Create()
{
Operations operation = _condition.Item1;
decimal a = _condition.Item2.GetNumber();
decimal b = _condition.Item3.GetNumber();
switch (operation)
{
case Operations.Addition:
return new Addition(a, b);
case Operations.Subtraction:
return new Subtraction(a, b);
case Operations.Multiplication:
return new Multiplication(a, b);
case Operations.Division:
return new Division(a, b);
default:
throw new Exception("Operator unexpected");
}
}
}
The thing is... I need to have more properties, like Result (in Arithmetic class only needs 1, in comparison 2 numbers we need two properties result), problem number, time (seconds) to resolve the problem.
The question is, I don't know where I should put these properties. One way it'll be adding some of them in Problem class, or create another class something like these:
ArithmeticProblem
Problem Problem <-- Here is Arithmetic class
Result
Time
Problem number
I only want to organize my classes as must be. Thanks in advance.
You can have different classes for result and in your Arithmetic class accept result type as generic:
and
Addition
can be as bellow:but if the number of parameters (like result, time, ...) are not fixed (dynamic) you can have a dictionary and store them in dictionary (their type) and write specific action and set them as value of dictionary.
I would suggest placing the Result, Time (to generate or solve), and Problem Number all inside the problem class. Each problem will have its own result, time, and number; they may as well be included. This relieves you of linking another class to each problem as well as having an all-inclusive problem class.