'Inheriting 2 base classes in .NET not possible?
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?
Solution 1:[1]
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
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Guru Stron |
