假设我们要定义一个类,允许基本的数学运算,称为“可添加的”。可添加的东西都可以加入。
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.虽然我曾尝试坚持尽可能的指引,我会很乐意修改的问题,以使其更清晰。
这一切都取决于你为什么想要那个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, ...);
你能行的:
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);
}
}
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
正如其他人在他们的答案已经提到的,你也可以使用仿制药占更多的数据类型。隐运营商(在我的例子中)是不是一定要用最好的选择,特别是如果你还是刚刚开始学习语言。