#ооп #компилятор #java #компиляция
Здравствуйте! Столкнулся со странным поведением компилятора, объясните пожалуйста,
почему происходит вывод разных строк.
class EntityModel{
public String name;
public EntityModel(){
this.name = "EntityModel";
}
public String getName(){
return this.name;
}
}
class Model1 extends EntityModel{
public String name;
public Model1(){
this.name = "Model1";
}
@Override
public String getName(){
return this.name;
}
}
Вызов:
EntityModel m = (EntityModel)new Model1();
System.out.println(m.name);
System.out.println(m.getName());
Вывод:
EntityModel
Model1
Код на ideone.com
Почему обращение к полю на прямую и через геттер дают разные результаты?
Ответы
Ответ 1
Хе :) Если коротко, то в Java методы виртуальные, а поля — нет. То есть, привязка метода к имени метода производится на этапе выполнения в соответствии с настоящим, динамическим типом объекта, а вот привязка поля — статическая, производится на этапе компиляции. Так сделано потому, что выставлять наружу открытое поле всё равно очень плохая практика, поэтому доступ к полям можно ускорить за счёт точного определения поля во время компиляции. А вот вызывая публичный метод, программист не ожидает вызова не самого «свежего» метода, так что здесь логичнее виртуальный вызов. (Впрочем, архитекторы C# считают не так, но это уже вопрос дизайна языков.) Это всё ещё один аргумент к тому, чтобы делать все поля private, и получать доступ к ним лишь через getter.Ответ 2
Потому что в первом случае считывается поле EntityModel.name, а во втором случае обращение к методу EntityModel.getName() приводит к вызову Model1.getName(), поскольку второй метод переопределяет первый. Так работает обращение к полям и методам, и об этом написано в любом учебнике.
Комментариев нет:
Отправить комментарий