I have X classes with different information and calculation methods that should be shared but could be overwritten, so:
class Rule1 {
int type = 1;
string name = "Rule";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule2 {
int type = 2;
string name = "Rule2";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule3 {
int type = 3;
string name = "Rule3";
public float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
What I want to write in the calling methods are like this:
class Calculator
{
public void Do(List<IRules> ruleList)
{
foreach(var rule in ruleList)
{
rule.Calc();
}
}
}
So how would my interface should have to look like and how to abstract the calc method as default implementation but overwriteable?
If you have an implementation that's correct for most inheritors but not all, mark it virtual and override it in a derived class:
public class BaseCalculation
{
public virtual float Calculate()
{
return 42;
}
}
public class HalfCalculation : BaseCalculation
{
public override float Calculate()
{
return 21;
}
}
You can now use the base class, BaseCalculation, instead of an interface. If you insist on still using an interface, then you can still define the Calculate() method in an interface and apply that to your base class:
public interface IRules
{
float Calculate();
}
public class BaseCalculation : IRules
{
// same as above
With the added benefit that you can apply this interface to other classes that also calculate something, but without any of the logic that's in BaseCalculation.
You can try this using an asbtract base class and polymorphism on Calc.
What is polymorphism
No need to use interface unless you have a real and good reason to do that.
What is the difference between an interface and a class
We use a protected constructor to propagate the parameters.
class Calculator
{
public void Do(List<RuleBase> ruleList)
{
foreach ( var rule in ruleList )
{
// do what you want with the result of rule.Calc();
}
}
}
public abstract class RuleBase
{
public int Type { get; private set; }
public string Name { get; private set; }
public abstract float Calc();
protected RuleBase(int type, string name)
{
Type = type;
Name = name;
}
}
public class Rule1 : RuleBase
{
public override float Calc()
{
return 1 + 2 + Type;
}
public Rule1()
: base(1, "Rule1")
{
}
protected Rule1(int type, string name)
: base(type, name)
{
}
}
public class Rule2 : Rule1
{
public Rule2()
: base(2, "Rule2")
{
}
protected Rule2(int type, string name)
: base(type, name)
{
}
}
public class Rule3 : RuleBase
{
public override float Calc()
{
return 3 + 4 + Type;
}
public Rule3()
: base(3, "Rule3")
{
}
protected Rule3(int type, string name)
: base(type, name)
{
}
}
If you want an interface create it and add it to RuleBase:
public interface IRule
{
float Calc();
}
public abstract class RuleBase : IRule
You are searching for inherited class and virtual method (wich allows override) :
class GenericRule {
int type = 1;
string name = "Rule";
public virtual float Calc()
{
return 1 + 2 + type; // SAME
}
}
class Rule3 : GenericRule
{
int type = 3;
string name = "Rule3";
public override float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
class Calculator
{
public void Do(List<GenericRule> ruleList)
{
foreach(var rule in ruleList)
{
rule.Calc();
}
}
}
Every class must support the interface. The implementation of method Calc in each class is not important. They can be the same or different.
If you want to have a standard implementation (virtual implementation), you could use a base class and overwrite the method in some classes (in your example Rule3).
If you do not want a standard implmentation (virtual implementation), you could use an abstract base class and overwrite the method in all classes (in your example Rule1, Rule2 and Rule3).
But that has nothing to do with the interface you want to use.
Complete working example (just using the interface):
using System;
using System.Collections.Generic;
namespace Temp
{
class Program
{
static void Main(string[] args)
{
var calc = new Calculator();
var rules = new List<IRule>() { new Rule1(), new Rule2(), new Rule3() };
calc.Do(rules);
Console.WriteLine(calc.GetTotal());
Console.ReadKey();
}
}
public interface IRule
{
float Calc();
}
public class Rule1 : IRule
{
int type = 1;
string name = "Rule";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
public class Rule2 : IRule
{
int type = 2;
string name = "Rule2";
public float Calc()
{
return 1 + 2 + type; // SAME
}
}
public class Rule3 : IRule
{
int type = 3;
string name = "Rule3";
public float Calc()
{
return 3 + 4 + type; // DIFFERENT
}
}
public class Calculator
{
private float _total = 0;
public void Do(List<IRule> ruleList)
{
foreach (var rule in ruleList)
{
_total += rule.Calc();
}
}
public float GetTotal()
{
return _total;
}
}
}
Related
So I am reading that in .net it is not possible to inherit a second base class. How then Can you create an object that serves 2 functions from 2 classes? For example I have an object that I want to be a tool and a weapon. The first is public class SmithHammer : BaseTool the second would look like public class SmithHammer : BaseBashing The 2 classes BaseTool and BaseBashing can be used for the same item just not at the same time apparently. As a weapon I have it coded this way to call on the base class BaseBashing.
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithyHammer : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
public override int OldMinDamage { get { return 6; } }
public override int OldMaxDamage { get { return 18; } }
public override int OldSpeed { get { return 40; } }
public override int InitMinHits { get { return 31; } }
public override int InitMaxHits { get { return 60; } }
[Constructable]
public SmithyHammer()
: base(0x13E3)
{
Weight = 8.0;
Layer = Layer.OneHanded;
Name = "Smith Hammer";
}
public SmithyHammer(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
}
}
And in the second use I have it as a tool
namespace Server.Items
{
[FlipableAttribute( 0x13E3, 0x13E4 )]
public class SmithHammer : BaseTool
{
public override CraftSystem CraftSystem{ get{ return DefBlacksmithy.CraftSystem; } }
[Constructable]
public SmithHammer() : base( 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
[Constructable]
public SmithHammer( int uses ) : base( uses, 0x13E3 )
{
Weight = 8.0;
Layer = Layer.OneHanded;
}
public SmithHammer( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
Is it not possible to make this item do both functions?
There is a mechanism for such scenarios - interfaces. Classes in C# does not support multiple inheritance but support implementing multiple interfaces. In this case you can create two interfaces (or even more) representing required contracts (i.e. interfaces):
public interface IBashing
{
string Damage { get; }
int OldStrengthReq { get; }
// ...
// rest of properties/methods for bashing/weapon
}
public interface ITool
{
CraftSystem CraftSystem { get; }
// ...
}
And implement them both the Hammer class:
public class SmithHammer : IBashing, ITool
{
public string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public int OldStrengthReq { get { return 45; } }
public CraftSystem CraftSystem { get{ return DefBlacksmithy.CraftSystem; } }
// rest of implemetations
}
And clients can use this hammer class instance via interface or using type testing. For example if you introduce IItem interface to store everything in the inventory (i.e interface IBashing : IItem and interface ITool : IItem) it can look like this:
var inventory = new List<IItem>();
// add some items
// pick some i'th item:
var item = inventory[i];
var tool = item as ITool; // or use pattern matching here
if(tool != null)
{
// use tool
}
else
{
....
}
Sharing implementation is not that easy with interfaces (unless you can and want to use default interface implementations) but can be achieved via composition and wrapping, i.e.:
public class SmithyHammerBashing : BaseBashing
{
public override string Damage { get { return WeaponControl.Settings.SmithyHammerDamage; } }
public override int OldStrengthReq { get { return 45; } }
}
public class SmithHammer : IBashing, ITool
{
private readonly SmithyHammerBashing Bashing = new SmithyHammerBashing(); // or construct some other way
public string Damage { get { return Bashing.Damage; } }
public int OldStrengthReq { get { return Bashing.OldStrengthReq; } }
// the same approach for ITool
}
I try to simulate the decorator pattern in C#.
So I have these classes:
public abstract class Car
{
// private string description;
public abstract string Descripton
{
get;
}
public abstract int Cost();
}
public abstract class CarDecorator : Car
{
protected Car _decorated;
//private string description;
public CarDecorator(Car decoratied)
{
this._decorated = decoratied;
}
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return _decorated.Cost();
}
public class EnhancedAutoPilot : CarDecorator
{
public EnhancedAutoPilot(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Enhanced autopilot";
}
}
public override int Cost()
{
return _decorated.Cost() + 5000;
}
}
public class ModelXS:Car
{
protected Car _decorated;
public string Description = "Model XS";
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return 5500;
}
}
public class ModelXXX : Car
{
protected Car _decorated;
public string Description = "ModelXXX";
public override string Descripton
{
get
{
return _decorated.Descripton;
}
}
public override int Cost()
{
return 73000;
}
}
public class RearFacingSeats:CarDecorator
{
public RearFacingSeats(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Rear Facing Seats ";
}
}
public override int Cost()
{
return _decorated.Cost() + 4000;
}
}
public class SmartAirSuspension: CarDecorator
{
public SmartAirSuspension(Car car):base(car)
{
this._decorated = car;
}
public override string Descripton
{
get
{
return _decorated.Descripton + ", Smart Air Suspension ";
}
}
public override int Cost()
{
return _decorated.Cost() + 2500;
}
}
class Program
{
static void Main(string[] args)
{
Car car = new RearFacingSeats(new SmartAirSuspension(new EnhancedAutoPilot()));
}
}
But then I get this error:
There is no argument given that corresponds to the required formal parameter 'car' of 'EnhancedAutoPilot.EnhancedAutoPilot(Car)'
Your Cars are wrong, they look like decorators but are not, in fact they are supposed to be just implementations of Cars. Like this one:
public class ModelXS : Car
{
public override string Descripton
{
get
{
return "Model XS";
}
}
public override int Cost()
{
return 5500;
}
}
After that you can call the constructors like in #Richard 's answer and you are golden.
and you can ditch
public EnhancedAutoPilot(Car car):base(car)
{
this._decorated = car; // <<-- this lines
}
because you do that assignment in the base constructor of the CarDecorator class already.
You're using new EnhancedAutoPilot() constructor without parameters and it requires a Car parameter in your contructor signature.
public EnhancedAutoPilot(Car car):base(car)
Another issue i see is that you have _decorated in your Car class. The decorated object should only be in the Decorator classes.
So i would modify your car classes this way :
public class ModelXXX : Car
{
public override string Descripton => "ModelXXX";
public override int Cost()
{
return 73000;
}
}
public class ModelXS : Car
{
public override string Descripton => "Model XS";
public override int Cost()
{
return 5500;
}
}
And main would look like this :
static void Main(string[] args)
{
Car car = new ModelXXX();
car = new EnhancedAutoPilot(car);
car = new SmartAirSuspension(car);
car = new RearFacingSeats(car);
Console.Writeline(car.Descripton);
}
The error is telling you that you are not passing a value to the EnhancedAutoPilot() contstructor. All of your decorators require a Car instance be passed, thus you must instantiate a car first, before calling your decorators.
It looks like ModelXS and ModelXXX are types of cars, so the Program class should be:
class Program
{
static void Main(string[] args)
{
Car decoratedCar =
new RearFacingSeats(
new SmartAirSuspension(
new EnhancedAutoPilot(
new ModelXS())));
}
}
I have a generic method
class Program {
Character CreateChar<T>() where T : new() {
T DChar = new T();
Character Char = new Character {
Name = DChar.Name,
Health = DChar.Health
};
return Char;
}
public static void Main() {
Character Char1 = CreateChar<Mage>();
}
}
Where I have a Character class, and that has the basic stuff like Name, Health, ect.
class Character {
public string Name { get; set; }
public int Health { get; set; }
}
But (this is like a game) I have some set types like "Mage".
class Mage {
public int Health {
get {
return 5;
}
}
}
So my idea was to make a generic method "CreateChar" so I can pass Mage to it like so in Main:
Character Char1 = CreateChar<Mage>();
However I can't seem to access DChar.Name or DChar.Health since "T does not contain a definition for 'Health'". So, is there a way to access the T method? Or is there just a better way of handling this?
In fact, now that I see it, "CreateChar();" is invalid as well because "an object reference is required for a nonstatic field". So I guess my question is, what is wrong, and how do I fix it?
In a generic method, you can only access the methods defined by the constraint on T (unless you use reflection or type checking/casting, both of which defeat the purpose of generics). If you constrain T to a Character (which I think you have to do to access Name and Health), then it should work (please post the Character class with relevant properties). But then in order to pass it a Mage, you'd have to have Mage inherit from Character.
Here's what I mean; first create an interface that defines properties that all characters will have (i.e. all public properties, methods, and events):
public interface ICharacter
{
string Name { get; set; }
string Description { get; }
int Health { get; set; }
}
Then we can create a base class called Character that implements the interface::
public class Character : ICharacter
{
public string Name { get; set; } = "Default Character";
public int Health { get; set; } = 5;
public string Description { get; protected set; } = "Default Description";
}
Next we create some character types that inherit the Character class:
public class Mage : Character
{
public Mage()
{
Name = "Default Mage";
Description = "Someone who uses or practices magic " +
"derived from supernatural or occult sources.";
}
}
public class Elf : Character
{
public Elf()
{
Name = "Default Elf";
Description = "A supernatural creature of folk tales, " +
"typically represented as a small, elusive figure " +
"in human form with pointed ears, magical powers, " +
"and a capricious nature.";
}
}
So now we can constrian our generic type T to the ICharacter interface, and we can access the Name and Health properties:
class Program
{
T CreateChar<T>() where T : ICharacter, new()
{
var result = new T();
result.Name += " (created in 'CreateChar' method)"; // Modify a property
return result;
}
// Rest of class omitted
}
You need to constrain T to an interface or a base class that contains the method you want to call.
I think you are looking at a factory pattern here. Does this help?
public class Character
{
protected Character(string name, int health)
{
Name=name;
Health=health;
}
public string Name { get; set; }
public int Health { get; set; }
}
public class Mage : Character
{
public Mage() : base("Evil Mage", 5)
{
this.Mana = 10;
}
public int Mana { get; set; }
}
public class Paladin : Character
{
public Paladin() : base("Holy Paladin", 8)
{
this.Shield = 2;
}
public int Shield { get; set; }
}
public static class ChatacterFactory
{
public static TChar Create<TChar>(string name) where TChar : Character, new()
{
var result = new TChar();
result.Name = name;
return result;
}
}
class Program
{
static void Main(string[] args)
{
Mage mage = ChatacterFactory.Create<Mage>("Boom Mage");
Paladin paladin = ChatacterFactory.Create<Paladin>("White Knight");
}
}
if I understood you right one of these should work for you:
//case 1
class Character1
{
static Character1 CreateChar<T>(T character) where T : CommonGameCharecterClassOrInterface, new()
{
Character1 achar = new Character1
{
Name = character.Name,
Health = character.Health
};
return achar;
}
}
class Character2
{
static Character2 CreateChar(dynamic character)
{
Character2 achar = new Character2
{
Name = character.Name,
Health = character.Health
};
return achar;
}
}
//case 2
class Character3
{
static Character3 CreateChar<T>() where T : CommonGameCharecterClassOrInterface, new()
{
T character = new T();
Character3 achar = new Character3
{
Name = character.Name,
Health = character.Health
};
return achar;
}
}
class Character4
{
static Character4 CreateChar<T>() where T : new()
{
dynamic character = new T();
Character4 achar = new Character4
{
Name = character.Name,
Health = character.Health
};
return achar;
}
}
I have a abstract Class figures which contains Abstract properties
and I am Overriding them in Derived class Rectangle and
Square. Now, iI want to implement this with Interface. But I can't use
constructor and neither I can't Declare the Variable inside the
Interface. So, how to implement this using Interface where Figures Should be Interface and Square and Rectangle should be class?
abstract class Figures
{
int Width;
int _cs;
public Figures(int Width)
{
CS = Width;
}
public abstract int getarea
{
get;
}
public abstract int getperm
{
get;
}
public abstract int CS
{
set;
}
public abstract void display();
}
class Square : Figures
{
int _CsS;
public Square(int c) : base(c)
{
}
public override int getarea
{
get
{
return (_CsS * _CsS);
}
}
public override int getperm
{
get
{
return (2 * _CsS * _CsS);
}
}
public override int CS
{
set
{
_CsS = value;
}
}
public override void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
}
class Rectangle : Figures
{
int H;
int _csr;
public Rectangle(int H, int W) : base(W)
{
this.H = H;
}
public override int getarea
{
get
{
return H * _csr;
}
}
public override int getperm
{
get
{
return 2 * H * _csr;
}
}
public override int CS
{
set
{
_csr = value;
}
}
public override void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
}
so how to implement this using Interface
By definition, an interface won't let you implement anything. You can only specify things.
So you will have to remove the ctor and the fields from the interface IFigures and re-implement them in every class. You could reuse an implementation with a abstract class FiguresBase: IFigures but that's not always the best design.
It all depends on why you want the interface and how you will use it.
You can do something like this:
interface IFigures
{
int getarea
{
get;
}
int getperm
{
get;
}
int CS
{
set;
}
void display();
}
Thenk you can implement this interface from your classes and do your logic inside the class itself. So instead of putting the properties logic inside of your abstract class you will have to write them in your child classes.
class Square : IFigures
{
int _CsS;
public Square(int c)
{
CS = c;
}
public int getarea
{
get
{
return (_CsS * _CsS);
}
}
public int getperm
{
get
{
return (2 * _CsS * _CsS);
}
}
public int CS
{
set
{
_CsS = value;
}
}
public void display()
{
Console.WriteLine("area={0} and perimeter={1}", getarea, getperm);
}
//here you have implemented properties
}
Your abstract class is a good thing. It lets you re-use code.
Interfaces (i.e. contracts) are also good if you want to achieve a loosely coupled system.
You can use abstract classes and interfaces together, to achieve both code reusability and loosely coupled parts.
public interface IFigures
{
int getarea();
}
public abstract class Figures : IFigures
{
public abstract int getarea();
//opportunity for code reuse
protected int getarea_internal()
{
throw new NotimplementedExcpetion();
}
}
public class Square : Figures
public class Rectangle: Figures
here is the answer
with class Diagram
Class Diagram of the Program
interface IFigures
{
int Getarea
{
get;
}
int GetPerm
{
get;
}
int CS
{
//get;
set;
}
}
abstract class Figures:IFigures
{
int _Cs;
public Figures( int _Cs)
{
CS = _Cs;
}
public abstract int Getarea
{
get;
}
public abstract int GetPerm
{
get;
}
public abstract int CS
{
//get;
set;
}
public abstract void display();
}
class Circle:Figures
{
int _r, _csc;
public Circle(int _r):base(_r)
{
CS = _r;
}
public override int Getarea
{
get
{
return (_r * _r);
}
}
public override int GetPerm
{
get
{
return (2* _csc * _csc);
}
}
public override void display()
{
Console.WriteLine("area of Circle={0}", (_r * _r));
Console.WriteLine("perimeter of rectangle={0}", (2 * _r * _r));
}
public override int CS
{
//get
//{
// return _csc;
//}
set
{
_csc = value;
}
}
}
class Rectangle:Figures
{
int _L, _csr;
public Rectangle(int _L,int _W):base(_W)
{
this._L = _L;
CS = _W;
}
public override int Getarea
{
get
{
return _csr * _L;
}
}
public override int GetPerm
{
get
{
return (2* _csr * _L);
}
}
public override void display()
{
Console.WriteLine("area of rectangle={0}", (_csr * _L));
Console.WriteLine("perimeter of rectangle={0}", (2* _csr * _L));
}
public override int CS
{
//get
//{
// return _csr;
//}
set
{
_csr = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Figures f = new Rectangle(3, 4);
f.display();
//f.CS = 5;
f.display();
Console.ReadKey();
}
}
I have the abstract class shown below. It's nested class B is where I would like to define new functions.
public abstract class A {
public string varA = "Default";
public class B {
public B() {
}
public abstract somethingCool(int[] val);
}
}
public class C:A {
//set B functions
}
Is there a particular reason you NEED B to be a nested class? Why not just let your A class have a property of type B? Also, the somethingCool method needs a return type.
public abstract class A
{
public string varA = "Default";
public B InstanceOfB { get; set; }
}
public abstract class B
{
public abstract void SomethingCool(int[] val);
}
public class C : A
{
public override void SomethingCool(int[] val)
{
//do something cool
}
}
I'm not sure what you are trying to do, but if you want to implement B's functions from C, then mark B as abstract and subclass it in C. You can then override the abstract somethingCool method. Something like this:
public abstract class A
{
public string varA = "Default";
public abstract class B
{
public B() {}
public abstract void somethingCool(int[] val);
}
public void Foo(B bar, int[] val)
{
bar.somethingCool(val);
}
}
public class C : A
{
// set B functions
public class D : A.B
{
public override void somethingCool(int[] val)
{
for (int i = 0; i < val.Length; ++i)
{
System.Console.Write(string.Format("{0} ", val[i]));
}
}
}
}
Note that you can also subclass B from outside C:
public class E : A.B
{
public override void somethingCool(int[] val)
{
for (int i = val.Length - 1; i >= 0; --i)
{
System.Console.Write(string.Format("{0} ", val[i]));
}
}
}
Results:
public class Test
{
public void Test()
{
int[] val = new int[] { 1, 2, 3 };
var C = new C();
var D = new C.D();
C.Foo(D, val); // should print 1 2 3
var E = new E();
C.Foo(E, val); // should print 3 2 1
}
}