#ооп #компилятор #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(), поскольку второй метод переопределяет первый. Так работает обращение к полям и методам, и об этом написано в любом учебнике.
Комментариев нет:
Отправить комментарий