有没有办法在实例化对象时隐藏/显示某些方法?

时间:2011-12-09 01:42:34

标签: c# java oop

当我编写一个遍历列表的类时会想到这个问题,方法next()和previous()会不断循环(例如,如果在最后一个对象,则返回它,然后将index重置为0 )

在构造函数中,我正在考虑添加一个布尔变量,如果为true,它就像一个只有next()方法且没有循环的常规迭代器。在这种情况下,使用上一个()方法是没有意义的。所以我很好奇,在这种情况下是否可以隐藏previous()方法。是否有可能以某种方式在Java或C#中实现这一点?

其他语言怎么样?

5 个答案:

答案 0 :(得分:6)

C#

可以通过使两个方法成为两个不同接口的一部分,并将对象转换为两个接口之一。例如:

interface ILoopingIterator
{
    void Next();
    void Previous();
}

interface INonLoopingIterator
{
    void Next();
}

class PlaysItBothWays : ILoopingIterator, INonLoopingIterator
{
    void ILoopingIterator.Next()
    {
         this.NextCore();
    }

    void ILoopingIterator.Previous()
    {
         // since this code will never be shared anyway, put it here
    }

    void INonLoopingIterator.Next()
    {
         this.NextCore();
    }

    private void NextCore()
    {
        // do stuff here; this method only exists so that code can be shared
    }
}

请注意,我已经明确地将类实现两个接口;这样,实例的用户强制选择他们想要使用该类的“模式”。您可以只显式实现一个接口(提供可以更改的“默认”模式)。

现在:

var looping = (ILoopingIterator) new PlaysItBothWays(); // selects mode A
var nonLooping = (INonLoopingIterator) new PlaysItBothWays(); // selects mode B

当然,这并不会阻止任何人将实例强制转换为“其他”界面,但如果程序员想要破坏他们自己的代码,他们也可以使用允许反射的东西。

爪哇

在Java中,以上是不可能的。您可以通过让类公开返回两个接口之一的实例的方法,并使用返回的值来实现。当然,对象实际上是一个工厂而不是服务提供商,所以这就像是在欺骗这个问题。

class PlaysItBothWays
{
    public ILoopingIterator asLooping() { return /* something */ }
    public INonLoopingIterator asNonLooping() { return /* something else */ }
}

答案 1 :(得分:4)

不应该将布尔值传递给构造函数,而应该只使用继承。

假设您有一个仅支持next()的基础迭代器。如果这是您需要的唯一功能,请将其实例化。

要提供更多功能,请继承此基础迭代器,创建一个名为TwoWayIterator的类或类似的类,并提供previous()方法。

这两个类都将共享一个公共超类,因此您可以将它们视为一个,并且可以通过将实例视为其基类来隐藏previous()方法。

答案 2 :(得分:2)

无法在静态类型语言中隐藏类似的方法。您可以做的最好的方法是实现方法,以便在调用方法时抛出异常(或等效)。

你可以做一些技巧,让它看起来像那些方法不存在。例如,让类实现两个接口,并使用不同的工厂方法来创建它们。但是,如果直接使用构造函数,或者您希望选择由构造函数或工厂方法参数的值确定,则它们不起作用。

答案 3 :(得分:0)

不是Java。您不能在运行时“隐藏”方法。我建议你创建两个接口 ,一个使用下一个方法,另一个扩展第一个方法并添加“previous”方法。然后,您可以使用2个工厂方法来创建其中一个类的实例。

请查看Java“Iterator”类

interface Iterator<T> {
    T next();
}

interface LoopingIterator<T> extends Iterator<T>{
    T previous();
}

然后你可以施展它们。与之前的C#回答相似

答案 4 :(得分:0)

你不能在运行时隐藏类成员(好吧,不管怎么说都不是C# - 不确定Java)。如果您担心在上下文中使用的Previous()方法没有做任何有用的事情,那么只需在此情况下抛出InvalidOperationException

值得注意的是,.NET已经具有标准的“迭代器”接口。它被称为IEnumerable(和通用版本IEnumerable<T>)并且仅向前。