使用面向对象的方法键入安全性

时间:2012-05-17 00:03:41

标签: oop language-agnostic computer-science liskov-substitution-principle

我正在尝试使用面向对象的方法来思考如何正确解决 这个问题。语言并不重要 - 我实际上想编写代码,但它更像是我关心的一般原则。

我想实现一个field:一组'数字',操作+, - ,*和/操作。此外,我希望能够实现更高的操作,如^和循环查找,其中(1)不需要为给定字段定义,但如果需要,可以覆盖(2),这是出于效率原因。

这就是问题所在。宣布

是不够的
FieldElement power (FieldElement base, FieldElement exponent)

因为我想要类型安全:不应该将有限字段的成员添加到整数。

也许我真正想要的是一个元对象,或超级界面,或者将不同类联系在一起的东西(一个用于整数,一个用于7-adics,一个用于有限域F_4等) 。或许还有更好的东西。

N.B。代码在答案中是受欢迎的(甚至是鼓励的),如果它具有启发性,但声明可能就足够了:大概这里的每个人都可以为至少几个领域写出明显的方法。


我会提到其他对我很重要的条件但是(显然)与主OO问题无关:我不希望字段元素带有它们的类型信息,而且我希望它们是轻量级的(因为我可能需要处理大型的场元素阵列)。这些需求可能无法实现 - 尽管坦率地说,我更倾向于放弃OO而不是效率。但是,无论如何,我都会对答案表示赞赏,因为即使除了手头的特定问题,我也有兴趣了解这些问题。

2 个答案:

答案 0 :(得分:2)

这称为二进制方法问题。快速谷歌搜索将揭示一些(很多)信息。特别是,Luca Cardelli等人的文章“On binary methods”给了这个主题一个彻底的处理。

您可能想学习一些Haskell,看看实用的编程语言如何处理这个问题。

编辑Loluca→Luca。该死的小手机屏幕及其较小的键盘;)

答案 1 :(得分:1)

我曾尝试在C#中表达这些概念,但我遇到了语言障碍:语言不够丰富,或者不够具体。例如,如果我像这样定义一个字段元素:

public abstract class FieldElement 
{
    public abstract FieldElement Add(FieldElement another);
    public abstract FieldElement SumInvert();
    public abstract FieldElement MultiplicationInvert();
    public abstract FieldElement MultiplyBy(FieldElement another);
    public abstract FieldElement One; //Multiplication neutral element
    public abstract FieldElement Zero; //Addition neutral element

    public FieldElement Subtract(FieldElement another)
    {
        return this.Add(another.SumInvert());
    }

    public FieldElement Divide(FieldElement another)
    {
        return this.MultiplyBy(another.MultiplicationInvert());
    }
    public virtual FieldElement Power(uint b)
    {
        if (b == 0)
            return this.One;
        else
        {
            FieldElement result = this;
            for (int i = 0; i < b - 1; i++)
                result = result.MultiplyBy(result);
            return result;
        }
    }
}

然后我定义这样的真实数字:

public class RealNumber : FieldElement
{
    public double Value { get; set; }

    public RealNumber(double value)
    {
        this.Value = value;
    }
    public override FieldElement Power(uint b)
    {
        return new RealNumber(Math.Pow(Value, b));
    }
    public override FieldElement Add(FieldElement another)
    {
        if (another.GetType() != typeof(RealNumber)) //Ugly typecast to enforce type-safety
            throw new ArgumentException("RealNumber expected in Add method");

        return new RealNumber(Value + (another as RealNumber).Value);
    }
}

然后我可以在Field Elements上定义一般操作(通过使用泛型):

public class FieldOperations<T> where T: FieldElement 
{
    public T Add(T a, T b)        
    {
        return a.Add(b) as T;
    }
    public T Multiply(T a, T b)
    {
        return a.MultiplyBy(b) as T;
    }
    public T Subtract(T a, T b)
    {
        return a.Subtract(b) as T;
    }
    public T Divide(T a, T b)
    {
        return a.Divide(b) as T;
    }
    public T Power(T a, uint b)
    {
        return a.Power(b) as T;
    }   
}

我将在代码中使用它:

public class TestFieldOperations
{
    public static void TestAddRealNumbers()
    {
        FieldOperations<RealNumber> operations = new FieldOperations<RealNumber>();
        RealNumber a = new RealNumber(0.5);
        RealNumber b = new RealNumber(0.7);
        RealNumber c = operations.Add(a, b);
        RealNumber d = operations.Power(c, 3);
    }
}

同样,我可以在Vector上使用FieldOperations,在InvMatrix上使用FieldOperations ...

能够以类型安全和面向对象的方式抽象Field操作的概念可以非常强大:能够在相同的抽象级别处理数字,向量和(可逆)矩阵算法。