Qubc
@Qubc
Ненавижу полисемию.

Почему в Java изменение интерфейса базового класса посредством модификации сигнатуры разрешено?

#include <iostream>

class Animal {
    public: virtual void sound() {
        std::cout << "Animal.sound()" << '\n';
    }
    public: virtual void sound(int i) {
        std::cout << "Animal.sound(int)" << '\n';
    }
};

class Cat : public Animal{
    
    public: void sound () override {
        std::cout << "Cat.sound()" << '\n';
    }
};


int main() {
    Cat * cat1 = new Cat();
    cat1 -> sound(); // Cat.sound()
    //! cat1 -> sound(1); // no matching function for call to 'Cat::sound(int)'
    delete cat1;
}


class Animal {
    public void sound() {
        System.out.println("Animal.sound()");
    }
    public void sound(int i) {
        System.out.println("Animal.sound(int)");
    }
}

class Cat extends Animal{
    @Override
    public void sound (){
        System.out.println("Cat.sound()");
    }
}

class Main {

    public static void main(String[] args) {
        Cat cat1 = new Cat();
        cat1.sound();// Cat.sound()
        cat1.sound(1);// Animal.sound(int)
     }

}
  • Вопрос задан
  • 188 просмотров
Решения вопроса 2
@MarkusD Куратор тега C++
все время мелю чепуху :)
Чтобы понять поведение кода в C++, нужно сперва разобраться с поиском имен в C++.
Коротко, поиск имен запускается всегда для каждого имени, которое встречается в коде, и связывает использованное в коде имя с конкретным, единственным из всех прочих, объявлением этого имени.

cat1 -> sound();
Тут по пунктам. Сперва UNL определит имя cat1 как переменную в локальном пространстве с типом Cat*.
Далее UNL же определит что в пространстве класса Cat есть метод sound.
Далее для определения перегрузки Cat::sound запустится ADL и найдет в пространстве только одну перегрузку - метод без параметров. ADL вернет объявление этой перегрузки, т.к. она удовлетворяет условиям вызова метода.

Отдельно отметить стоит то, что это именно писатель определил в пространстве класса только одну перегрузку метода sound. Алгоритм ADL довольно строг и не будет искать объявления где-либо еще.
Именно поэтому при данном определении класса Cat код cat1 -> sound(1); трансляцию никогда не пройдет. Просто потому что в пространстве класса написана только одна перегрузка метода.

Что делать, когда перегрузки из родительского класса нужны все, но замещать их все в классе дочернем нужды нет?
Тут на помощь приходит ключевое слово using[?].
Это слово нужно использовать в контексте делегирования из пространства родительского класса. Определение класса Cat должно быть таким.
class Cat : public Animal
{
public:
	// Delegate all overloads of `sound`.
	using Animal::sound;
	
	void sound () override
	{
		std::cout << "Cat.sound()" << '\n';
	}
};


В этом случае код cat1 -> sound(1); пройдет трансляцию и приведет к вызову void Animal::sound(int i).
Ответ написан
mayton2019
@mayton2019 Куратор тега Java
Bigdata Engineer
Несмотря на то что java/c++ формально являются ООП языками, многие вещи
с перегрузкой у них реализованы по разному. В случае с методом sound в Java
скорее всего будет создано просто 2 метода (разные сигнатуры).
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@dima20155
you don't choose c++. It chooses you
А вы попробуйте в С++ реализации добавить спецификатор override к методу и поймёте что sound не переопределен. Полагаю, аналогичное поведение и в java.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы