переопределение, перегрузка и скрытие в ООП - PullRequest
2 голосов
/ 19 августа 2011

Я знаю эти 3 понятия.

Но я помню, что было другое определение: Скажем, базовый класс имеет 2 виртуальных метода: Foo () и Foo (int a). Есть ли правило, что при переопределении производного класса Foo (int a) должен переопределять все другие перегрузки Foo?

Это было на Яве? Я считаю, что это не существует в C #.

Спасибо

Ответы [ 6 ]

6 голосов
/ 19 августа 2011

Нет, такого правила нет, по крайней мере, в Java.Такое правило было бы невероятно ограничивающим, поскольку иногда подкласс имеет только новую реализацию одной из этих перегрузок и т. Д.

4 голосов
/ 19 августа 2011

Это не правило в Java.Вы думали об интерфейсе?Если класс реализует интерфейс, он должен иметь реализацию каждого метода, объявленного в интерфейсе.

2 голосов
/ 19 августа 2011

Нет На самом деле это не относится к Java.Однако, если вы реализуете интерфейс, вам нужно иметь реализацию для всех методов в нем.Но когда вы используете extends, то есть наследование, вы переопределяете нужные методы, и в этом случае Foo (int x) отличается от Foo () независимо от того, совпадают ли их типы возврата.

2 голосов
/ 19 августа 2011

C ++:

Вы имеете в виду имя, скрывающее в C ++.Если у вас есть класс с переопределенными методами, и вы расширяете этот класс переопределением одного из переопределенных методов, вам необходимо переопределить все перегруженные методы.В противном случае вызовы не переопределенных перегруженных в расширенном классе не будут работать.

Например:

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 такого понятия нет,Вы можете попробовать это сами.Обратите внимание, что все методы Java являются виртуальными по умолчанию в соответствии с виртуальными методами C ++.

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
    }
}

В стороне:

Надеюсь, вы не имеете в виду расширение абстрактного класса- если вы расширяете абстрактный класс, вам нужно переопределить все абстрактные методы, иначе ваш класс должен быть объявлен как абстрактный.

Хотя все методы реализованного интерфейса должны быть реализованы.

0 голосов
/ 19 августа 2011

просто чтобы добавить к тому, что уже сказали другие, в java каждый метод четко идентифицируется по полной сигнатуре, которая включает тип возвращаемого значения, имя и аргументы. поэтому, когда вы определяете абстрактный метод (виртуальную функцию), вы определяете его как абстрактный только для той функции с ее сигнатурой.

во всяком случае, вы могли бы попробовать это в своей IDE для удовольствия и получить ответ через минуту. : P

0 голосов
/ 19 августа 2011

Однако, если вы хотите создать неабстрактный класс (расширяющий базовый класс), вы должны реализовать все абстрактные методы.

...