当我编写一个遍历列表的类时会想到这个问题,方法next()和previous()会不断循环(例如,如果在最后一个对象,则返回它,然后将index重置为0 )
在构造函数中,我正在考虑添加一个布尔变量,如果为true,它就像一个只有next()方法且没有循环的常规迭代器。在这种情况下,使用上一个()方法是没有意义的。所以我很好奇,在这种情况下是否可以隐藏previous()方法。是否有可能以某种方式在Java或C#中实现这一点?
其他语言怎么样?
答案 0 :(得分:6)
可以通过使两个方法成为两个不同接口的一部分,并将对象转换为两个接口之一。例如:
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>
)并且仅向前。