【问题标题】:Is there a way to hide/show certain methods when instantiating an object?实例化对象时有没有办法隐藏/显示某些方法?
【发布时间】:2011-12-09 01:42:34
【问题描述】:

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

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

其他语言呢?

【问题讨论】:

    标签: c# java oop


    【解决方案1】:

    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

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

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

    【讨论】:

    • 您可以在 Java 中通过在两个接口中为 next 方法使用不同的名称来执行几乎相同的操作。
    【解决方案2】:

    您应该简单地使用继承,而不是将布尔值传递给构造函数。

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

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

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

    【讨论】:

      【解决方案3】:

      不可能在静态类型语言中隐藏这样的方法。您能做的最好的事情是实现该方法以在调用该方法时抛出异常(或等效)。

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

      【讨论】:

        【解决方案4】:

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

        请查看Java“迭代器”类

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

        然后你就可以施放它们了。和之前的C#回答类似

        【讨论】:

          【解决方案5】:

          您不能在运行时隐藏类成员(好吧,无论如何都不能在 C# 中 - 不确定 Java)。如果您非常担心 Previous() 方法被用在它没有做任何有用的事情的上下文中,那么在这种情况下只需让它抛出 InvalidOperationException

          同样值得注意的是,.NET 已经有了标准的“迭代器”接口。它被称为IEnumerable(和通用版本IEnumerable&lt;T&gt;)并且是只转发的。

          【讨论】:

            猜你喜欢
            • 2018-01-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-02
            相关资源
            最近更新 更多