Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, how does one implement an abstract class that calls itsself in a function e.g. such as a class of Addable objects?

Say we want to define a class that allows basic arithmatic, called 'Addable'. Addable things can be added.

abstract class Addable
{
   public abstract Addable Add(Addable X, Addable Y)
}

What is the correct way to implement an Addable? The following doesn't work, it gives:

Number does not implement inherited abstract member Addable.Add(Addable, Addable).

class Number : Addable
{
     public int Value;

     public Number(int Val)
     {
        Value = Val;
     }

     public Number Add(Number X, Number Y)
     {
         return new Number(X.Value + Y.Value);
     }
}

I think the problem is that Add takes (Number,Number) as its arguements which aren't generic enough, but I do not know how to proceed.

Edit: As some people have requested to know what this is to be used for, let me elaborate. I am using an algorithm that relies on taking the maximum of several objects. Depending on the use case, these objects are numbers, or distributions. To stay with the example above I will pretend I need to add these numbers or distributions. So I want to have code that looks something like:

Addable LongAlgorithm(Addable X, Other parameters)
{
   ... // Lots of code that may contain X
   Z = Add(X,Y)
   ... // Code Using Z.

   return Answer // Answer is of the same type as X in the input.
}

Edit 2: With the feedback given this question seems to be drifting into the realm of "Interface vs Base class". Perhaps others who read this question might find that question illuminating.

I hope the question is clear, I am new to S.O. and although I have tried to stick to the guidelines as much as possible, I will be happy to modify the question to make it clearer.

like image 253
Kazadstairs Avatar asked Dec 18 '22 18:12

Kazadstairs


1 Answers

It all depends on why you want that Addable base class, and how it will be used. It's worth updating your question to explain this. Here's one possibility, which might not meet your use-case:

public interface IAddable<T>
{
    T Add(T x, T y);
}

public class Number : IAddable<Number>
{
    public int Value { get; set; }

    public Number(int value)
    {
        Value = value;
    }

    public Number Add(Number other)
    {
        return new Number(Value + other.Value);
    }
}

You could of course use an abstract base class as well here, if there was a need:

public abstract class Addable<T>
{
    public abstract T Add(T x, T y);
}

If you want to make sure that types can only do class Foo : IAddable<Foo> and not class Foo : IAddable<Bar>, then you can add a generic type restriction:

public interface IAddable<T> where T : IAddable<T>
{
    T Add(T x, T y);
}

In response to your edit:

Use my types from above and do this:

T LongAlgorithm<T>(T x, Other parameters) where T : IAddable<T>
{
   ... // Lots of code that may contain x
   T z = x.Add(y);
   ... // Code Using z

   return z;
}

Note that I've changed your Add method so that it's an instance method, which adds itself to another instance.

If you wanted to keep the signature as Add(x, y), you probably want something like this:

public class Number
{
    public int Value { get; set; }
    public Number(int value)
    {
        Value = value;
    }
}

public interface IAdder<T>
{
    T Add(T x, T y);
}

public class NumberAdder : IAdder<Number>
{
    public static readonly NumberAdder Instance = new NumberAdder();
    private NumberAdder() { }
    public Number Add(Number x, Number y)
    {
        return new Number(x.Value + y.Value);
    }
}

T LongAlgorithm<T>(T x, IAdder<T> adder, Other parameters)
{
   ... // Lots of code that may contain x
   T z = adder.Add(x, y);
   ... // Code Using z

   return z;
}

Then call it like

Number z = LongAlgorithm(new Number(3), NumberAdder.Instance, ...);
like image 121
canton7 Avatar answered Feb 01 '23 23:02

canton7