简体   繁体   English

在Java中怎么做?在C ++中,什么改变了重写的方法可见性?

[英]How to do in java what in C++ is changing an overridden method visibility?

In C++ it's possible to change an overridden method's visibility. 在C ++中,可以更改重写方法的可见性。 I find this feature very useful sometimes, for example: 我有时发现此功能非常有用,例如:

consider you want a class to have some debugging methods, but you don't want them to be visible as public class interface. 考虑到您希望一个类具有一些调试方法,但是您不希望它们在公共类接口中可见。 You could have something like: 您可能会喜欢:

class IDebuggable {
public:
 virtual void debug(std::string s) = 0;
};

class MyProductionClass: public IDebuggable

public:
 void myClassMethod() {}

private:
 virtual void debug(std::string) {
  // do some debug here
 }

};

To do so, when using an object of class MyProductionClass, all I can access is MyProductionClass::myClassMethod() (the production interface). 为此,当使用类MyProductionClass的对象时,我只能访问MyProductionClass :: myClassMethod()(生产接口)。

However, if I want to use it's debugging features, I can do this: 但是,如果要使用它的调试功能,则可以执行以下操作:

MyProductionClass* obj = new MyProductionClass();
IDebuggable* iface = obj;

iface->debug("Hello World");

I've found in my experience this "feature" quite useful. 根据我的经验,我发现此“功能”非常有用。 In java this is not possible as it's forbidden to change the visibility of an inherited method. 在Java中,这是不可能的,因为禁止更改继承方法的可见性。 Is there another way I can achieve the above artifact? 还有其他方法可以实现上述工件吗?

Thanks a lot 非常感谢

Personally, I hate when people change method visibility this way. 就个人而言,我讨厌人们以这种方式更改方法的可视性。 I think it's much better to preserver the visibility and expose interfaces, but not the classes themselves, for external users. 我认为最好为外部用户保留可见性并公开接口,而不是类本身。 Like: 喜欢:

class MyInterface {...}
class MyDebugable {...}

class MyClass : MyInterface, MyDebugable {...}

Give MyInterface to the users and user MyClass internally. MyInterface内部提供给用户和用户MyClass

By changing visibility you violate Liskov substitution principle . 通过更改可见性,您违反了Liskov substitution principle At the same time your users still can cast to IDebuggable and call your 'private' methods 同时,您的用户仍然可以转换为IDebuggable并调用您的“私有”方法

You cannot reduce visibility of inherited method. 您不能降低继承方法的可见性。 This is right. 这是对的。 However you can create as many interfaces as you want and make you class to implement these interfaces. 但是,您可以根据需要创建任意数量的接口,并使您进行分类以实现这些接口。 Then if your client works with specific interface it "does not have access" to other even public methods. 然后,如果您的客户端使用特定的接口,则它“无权访问”其他公用方法。

Here is an example. 这是一个例子。

public interface Foo {
    public void foo();
} 

public interface Bar {
    public void bar();
} 

public class MyClass implements Foo, Bar {
    public void foo() {}
    public void bar() {}
}

Here is how we use this class: 这是我们使用此类的方法:

Foo f = new MyClass();

You can call foo() here and cannot call bsar() . 您可以在此处调用foo() ,而不能调用bsar() You can however cast Foo to Bar and then use bar() method. 但是,您可以将FooBar ,然后使用bar()方法。

In Java you can increase method visibility but you can't reduce it when subclassing. 在Java中,您可以增加方法的可见性,但在子类化时却不能降低它的可见性。 This is due to the fact that you may access object via parent class (interface) and all methods defined in parent class should be available to caller. 这是由于您可以通过父类(接口)访问对象,并且父类中定义的所有方法应对调用者可用。

So the following is possible: 因此,以下是可能的:

class A {
    protected void foo() {}
}

class B extends A {
    @Override
    public void foo() {}
}

This is (for God's sake) not possible in Java. (出于上帝的考虑)这在Java中是不可能的。 Furthermore, what you want could be much better achieved by using a logging framework with different configurations for development/production. 此外,通过为开发/生产使用具有不同配置的日志记录框架,可以更好地实现您想要的目标。

Implement a feature discovery like this: 实施这样的功能发现:

class A {

    public final T <T> lookup(Class<T> klazz) {
        return map.get(klazz);
    }

    public A() {
        map.put(IDebugable.class, new IDebuggable() { ... };
    }
}

A a = ...;
a.lookup(IDebuggable.class).debug();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM