#java #design-patterns #inheritance #interface
#java #шаблоны проектирования #наследование #интерфейс
Вопрос:
Я пришел с опытом веб-разработки. Недавно я немного поиграл с Java и столкнулся со следующей проблемой, которая, по-видимому, связана со строгими интерфейсами и типизацией данных, которые являются большей частью Java, чем PHP.
Я использую существующий физический движок (Phys2D) для разработки своего рода игры. Этот физический движок имеет Body
объекты, управляемые World
, и к ним применяются различные силы по мере изменения ступенчатого мира. Для искусственного интеллекта в игре важно, чтобы тела имели цвета (чтобы их можно было распознать), но это не поддерживается физическим движком, поэтому я создал подкласс и расширил Body
класс, включив в него это — http://pastebin.com/1nLYWg3w . Теперь, когда я создаю эти Body
экземпляры, я могу получить их обратно из World
и получить их цвета.
Однако Netbeans утверждает, что это
cannot find symbol
symbol: method getColour()
location: class net.phys2d.raw.Body
потому что Body
объекты, возвращаемые интерфейсом физического движка, не содержат этого метода. Я знаю, что во время выполнения все Body
объекты, которые передаются в World
, на самом деле будут объектами ColouredBody
типа, и поэтому этот метод будет определен в их интерфейсах.
Как я могу прикрепить цвета к Body
объектам и не создавать пугающих подчеркиваний и предупреждений? Я понимаю, что могу изменить сам Phys2D, но, если отбросить потенциальные лицензионные ограничения (в лицензии указано, что вы можете сделать это с помощью Phys2D), мне сказали, что это плохая практика.
Комментарии:
1. Я связался с pastebin, чтобы не загромождать вопрос. Пожалуйста, сообщите, будет ли это более уместно в самом сообщении. Кроме того, если есть какой-либо способ, которым я могу сделать сообщение более общим для других людей, пожалуйста, отредактируйте или запросите необходимые изменения.
Ответ №1:
Если во время выполнения вы знаете, что все ваши Body
объекты на самом деле ColouredBody
, то вы можете привести эти объекты к ColouredBody
и вызвать getColour
:
Body body = ...;
ColouredBody colouredBody = (ColouredBody) body;
colouredBody.getColour();
Ответ №2:
На самом деле, я бы сказал, что было бы совершенно неплохо добавить свойство colour к классу Body самого движка.
Если вы не можете или не хотите этого делать, все, что вам нужно сделать, это привести Body
экземпляры к ColouredBody
перед их использованием:
((ColouredBody)body).getColour();
Это сообщает компилятору «Я знаю, что body
это действительно экземпляр ColouredBody
, поэтому позвольте мне использовать его как один», но если в любой момент окажется, что это не так, вы получите ClassCastException
.
Комментарии:
1. Большое спасибо. Я собираюсь отредактировать существующий класс, поскольку это кажется намного более элегантным. Если бы мне не разрешалось редактировать библиотеку, и если бы не было более простых вариантов, я бы использовал cast.
Ответ №3:
Вы можете привести к конкретному типу:
ColouredBody cbody = (ColouredBody) body;
желательно, просто чтобы избежать проблем, вы можете проверить, действительно ли это так:
if (body instanceof ColouredBody) {..}
Обратите внимание, что понижение (от более общего к более конкретному классу) обычно считается плохой практикой.
Если это возможно, вы можете попытаться расширить World
с ColouredWorld
помощью Body
и переопределить методы, которые возвращают ColouredBody
значение return, на return, которые возвращают, и также хранить тела в соответствующей коллекции, но это может быть излишним в зависимости от сложности.