'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