在C#中,如何实现一个在一个函数调用自身例如一个抽象类如类可添加的对象?

问题描述 投票:4回答:3

假设我们要定义一个类,允许基本的数学运算,称为“可添加的”。可添加的东西都可以加入。

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

什么是实现可加成的正确方法?以下是不行的,它给:

数未实现继承的抽象成员Addable.Add(可添加,可添加)。

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);
     }
}

我认为这个问题是需要添加(数字,数字)作为其arguements不属于通用不够,但我不知道如何着手。

编辑:一些人要求知道这是什么将用于,让我解释一下。我使用的是依赖于以最大的几个对象的算法。根据不同的使用情况下,这些对象是数字,或分布。留在上面的例子中,我会假装我需要添加这些数字或分布。所以我想有一些代码看起来是这样的:

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.
}

编辑2:有鉴于这一问题的反馈似乎漂流到的“Interface vs Base class”的境界。也许其他人谁看这个问题可能会发现,问题的照明。

我希望这个问题是清楚的,我是新来S.O.虽然我曾尝试坚持尽可能的指引,我会很乐意修改的问题,以使其更清晰。

c# abstract-class
3个回答
8
投票

这一切都取决于你为什么想要那个Addable基类,以及如何使用。这是值得更新您的问题来解释这一点。这里有一个可能性,这可能无法满足您的使用情况:

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);
    }
}

你当然可以使用一个抽象基类,以及在这里,如果有必要:

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

如果你想确保类型只能做class Foo : IAddable<Foo>而不是class Foo : IAddable<Bar>,那么你可以添加一个泛型类型的限制:

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

在回答您的编辑:

从上面使用我的类型和做到这一点:

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;
}

请注意,我已经改变了你的Add方法,以便它是一个实例方法,增加了自己的另一个实例。

如果你想保持签名Add(x, y),你可能想是这样的:

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;
}

然后调用它像

Number z = LongAlgorithm(new Number(3), NumberAdder.Instance, ...);

2
投票

你能行的:

abstract class Addable<T>
{
   public abstract T Add(T X, T Y);
}

class Number : Addable<Number>
{
     public int Value;

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

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

1
投票
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);
     }
}

需要是

class Number : Addable
{
     public int Value;

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

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

当你声明的抽象方法,你需要准确地实现它,因为它被宣布,否则将无法编译。不过不要担心,因为你Number类从Addable派生,你仍然可以调用的方法,无需转换。


编辑:

回首代码,有很多,可以在这里得到改善。

举例来说,你暴露的变量值 - 这是对封装的法律(OOP)。我建议在这种情况下使用属性。此外,正如在评论中提到(我忽略了这个事实),该属性会在你的基类中去。

说到基类的,在这种情况下,这将是明智的把这个给一个接口,因为你不打算使用任何东西,只声明。

当你想揭露的东西蓝图使用的接口。当你想揭露一些框架使用抽象类。

基本上你能想到像房子的建设计划(蓝图)的接口。它声明说,房子的结构。想想一个抽象类,作为房子的框架。这不是完全结束,但你通常可以站在城墙内,便干 - AKA它已经暴露了一些功能。

这里有一个如何解决你的问题的想法。这不是最优雅的,但它应该给你一个总体思路。

其实,写下来后,一个更优雅的解决方案来考虑:使用结构。

public interface IAddable {

    /// <summary >
    /// This is the value we want.
    /// </summary>
    int Value { get; set; }

    IAddable Add(IAddable x, IAddable y);

}

public class Number : IAddable {

    public Number() { }

    public Number(int num) => Value = num;

    public int Value { get; set; }

    public IAddable Add(IAddable x, IAddable y) {
        return (Number)(x.Value + y.Value);
    }

    public static implicit operator Number(int num) => new Number(num);
    public static implicit operator Number(double num) => new Number((int)num);
    public static implicit operator int(Number num) => num.Value;
}

编辑2

正如其他人在他们的答案已经提到的,你也可以使用仿制药占更多的数据类型。隐运营商(在我的例子中)是不是一定要用最好的选择,特别是如果你还是刚刚开始学习语言。

© www.soinside.com 2019 - 2024. All rights reserved.