覆盖,重载和隐藏在OOP中

时间:2011-08-19 18:40:47

标签: java override

我知道这三个概念。

但我记得还有另一个定义: 假设基类有2个虚方法:Foo()和Foo(int a)。 是否有任何规则,当派生类重写Foo(int a)时必须覆盖Foo的所有其他重载?

是Java吗?我相信它在C#中不存在。

由于

6 个答案:

答案 0 :(得分:6)

不,没有这样的规则,至少在Java中没有。这样的规则将具有令人难以置信的限制,因为有时子类只有其中一个重载的新实现等。

答案 1 :(得分:4)

这不是Java中的规则。你在想一个界面吗?如果一个类实现了一个接口,那么它必须具有在接口上声明的每个方法的实现。

答案 2 :(得分:2)

<强> C ++:

您所指的是C ++中的name hiding。当你有一个具有覆盖方法的类,并且你扩展这个类覆盖其中一个覆盖的方法时,你需要覆盖所有重载的方法。如果没有,在扩展类中调用非重写的重载将不起作用。

例如:

class Base {
    public:
        virtual void A (int);
        virtual void A (int, int);
};
void Base::A(int i) {
    std::cout << “Hi\n”;
}
void Base::A (int i, int j) {
    std::cout << “Bye!!\n”;
}

假设您只覆盖其中一个方法:

class Sub: public Base {
    public:
        void A(int);
};
void Sub::A(int i) {
    std::cout << “Hey, La!\n”;
}
void main () {
    Sub a;
    a.A(1);
    a.A(1, 1);//won't compile
}

第二次通话无效,因为A(int, int)不可见。这是名字隐藏。 如果您想绕过这一点,可以使用using关键字,如下所示:

class Sub: public Base {
    public:
        void A(int);
        using Base::A;
};
void Sub::A(int i) {
    std::cout << “Hey, La!\n”;
}
void main () {
    Sub a;
    a.A(1);
    a.A(1, 1);//will compile
}

Java:

Java没有这样的概念。你可以自己尝试一下。请注意,根据虚拟C ++方法,默认情况下所有Java方法都是虚拟的。

public class Base {
    public void A() {
        System.out.println("Hi");
    }
    public void A(int i, int j) {
        System.out.println("Bye");
    }
}

public class Sub extends Base {
    public void A() {
        System.out.println("Hey, La!");
    }
}

public class Test {
    public static void main(String[] args) {
        Sub a = new Sub();
        a.A();
        a.A(1, 1);//perfectly fine
    }
}

<强>除了:

我希望你不是指扩展一个抽象类 - 如果扩展一个抽象类,你需要覆盖所有抽象方法,否则你的类必须被声明为抽象类。

实现接口的所有方法都需要实现。

答案 3 :(得分:2)

否实际上不适用于Java。但是,如果实现接口,则需要实现其中的所有方法。但是当你使用extends即继承时,你会覆盖你想要的方法,在这种情况下,Foo(int x)与Foo()不同,无论它们的返回类型是否相同。 / p>

答案 4 :(得分:0)

但是,如果要创建非抽象类(扩展基类),则必须实现所有抽象方法。

答案 5 :(得分:0)

只是为了添加其他人已经说过的内容,在java中,使用包含其返回类型,名称和参数的完整签名来清楚地识别每个方法。所以当你定义一个抽象方法(虚函数)时,你只能将它定义为具有签名的那个函数的抽象。

无论如何你可以在你的IDE中尝试这个以获得乐趣,并且会在一分钟内得到答案。 :P