#java #inheritance
#java #наследование
Вопрос:
В настоящее время я работаю над каким-то школьным проектом; мы разрабатываем простую RPG, но, похоже, я подвергаю сомнению некоторые части моего Java-кода.
У меня есть Abstract
класс с именем Item
, затем у меня есть классы Armor
и Weapon
, которые оба наследуются от Item
. Оба Armor
и Weapon
имеют некоторые атрибуты, которых Item
нет.
Итак, в моей оболочке базы данных у меня есть loaditem
метод, который получает статистику и создает экземпляр моего класса (читайте комментарии в коде):
public Item loadItem(int itemID)
{
// Setting item, as a Item, as it can be both Weapon or Armor
Item item;
try {
// Build prepared statement
PreparedStatement stmt = con.prepareStatement("SELECT * FROM item WHERE iid = ?");
// Set Parameter
stmt.setInt(1, itemID);
// Execute the query
ResultSet rs = stmt.executeQuery();
// Get row
rs.first();
// Set all values and keys
if(rs.getString("type").equals("weapon")) {
item = new Weapon();
// SetDamage is unique to Weapon, and setDefense to armor
item.setDamage();
}else {
item = new Armor();
item.setDefense()
}
item.setIid(rs.getInt("iid"));
item.setName(rs.getString("name"));
item.setDescription(rs.getString("description"));
item.setSellValue(rs.getInt("sellvalue"));
item.setBuyValue(rs.getInt("buyvalue"));
item.setStrength(rs.getInt("strength"));
item.setAgility(rs.getInt("agility"));
item.setEndurance(rs.getInt("endurance"));
У меня нет проблем с установкой экземпляра Weapon
или Armor
в item, но он не может найти методы в классах.
Действительно ли мне нужно создавать как объект weapon, так и объект armor и возвращать после ввода?
Ответ №1:
Да, если вы собираетесь вызвать метод экземпляра, «целевое» выражение вызова метода должно иметь тип во время компиляции, который, как известно, имеет соответствующий метод. Компилятору необходимо разрешить вызовы методов во время компиляции. (Любое разрешение перегрузки выполняется во время компиляции; фактическая реализация определяется во время выполнения, конечно, на основе полиморфизма.)
Неясно, зачем вам в первую очередь нужна item
переменная. Похоже, вам просто нужно:
if (rs.getString("type").equals("weapon")) {
Weapon weapon = new Weapon();
weapon.setDamage();
return weapon;
} else {
Armor armor = new Armor();
armor.setDefense();
return armor;
}
Это предполагает, что вы хотите немедленно вернуться — ваш код был усечен, поэтому это непонятно. Если вам действительно нужна item
переменная, вы можете просто присвоить weapon
или armor
тому item
, где у меня есть инструкции return выше.
РЕДАКТИРОВАТЬ: похоже, что это так, поэтому у вас было бы:
// I'd still declare `item` as late as possible, i.e. here rather than
// outside the `try` block, unless you *also* need it outside the try block...
Item item;
if (rs.getString("type").equals("weapon")) {
Weapon weapon = new Weapon();
weapon.setDamage();
item = weapon;
} else {
Armor armor = new Armor();
armor.setDefense();
item = armor;
}
// Other code using `item` here
На самом деле, вы вполне можете поместить код для инициализации оружия в отдельный метод. Тогда вы могли бы использовать:
String type = rs.getString("type");
Item item = type.equals("weapon")) ? createWeapon() : createArmor();
Комментарии:
1. Потому что, если я создам экземпляр внутри if, я смогу использовать его только там. Элемент сам по себе содержит множество статистических данных, поэтому, если бы я использовал ваш пример, мне пришлось бы написать 10 установщиков как в if, так и в else. Что просто кажется глупым. Но если нет другого пути. 🙂
2. @MartinElvarJensen: Ну, если бы вы на самом деле показали другой код, использующий
item
послеif
инструкции, я бы написал ответ по-другому. Я не могу угадать код, который вы не показали и не описали!3. Спасибо, Джон, ты мне очень помог :). Также спасибо всем остальным за потраченное время.
Ответ №2:
Вы можете сделать это следующим образом:
if (...) {
Weapon w = new Weapon();
// SetDamage is unique to Weapon, and setDefense to armor
w.setDamage();
item = w;
} else {
...
}
После этого if
блок / последовательность можно использовать item
перед возвратом. Но вы можете вызывать на нем только методы Item
класса. Аналогично, вызывающие ваш loadItem
метод могут использовать методы из Item
класса только для возвращаемого вами значения, если они аккуратно не используют приведение.
Ответ №3:
Чтобы вызвать метод, уникальный для «Оружия», вы должны привести указатель элемента к оружию, таким образом:
Weapon weaponPointer = (Weapon)item;
weaponPointer.setDamage();
Комментарии:
1. Учитывая, что он создается в предыдущей строке, здесь нет необходимости приводить — просто используйте отдельную переменную.
2. Верно, но это работает в общем случае, чего не делают другие.
Ответ №4:
функция item = new Weapon() приведет к тому, что элемент будет ссылаться на экземпляр оружия, но элемент не станет оружием, чтобы ссылаться на методы Weapon of Armor, вы можете выполнить одно из следующих действий:
if (rs.getString("type").equals("weapon")) {
Weapon weapon = new Weapon();
weapon.setDamage();
return weapon;
} else {
Armor armor = new Armor();
armor.setDefense();
return armor;
}
или
if (rs.getString("type").equals("weapon")) {
item = new Weapon();
((Weapon)item).setDamage();
} else {
item = new Armor();
((Armor)item).setDefense();
}
возвращаемый элемент
Комментарии:
1. Итак, вы действительно применяете это в своем втором примере?
Ответ №5:
Следует различать тип экземпляра и ссылочный тип;
Item myItem = new Weapon();
Тип экземпляра: Оружие
Тип ссылки: элемент
Итак, если вы вызываете метод в MyItem, это может быть только метод класса Item. Потому что ваш ссылочный тип — Item .
В вашем случае вы хотите вызвать метод Weapon, поэтому ваш ссылочный тип тоже должен быть Weapon.
Weapon myWeapon = new Weapon();
item.setDamage(); // method of Weapon class, it's ok
Обратите внимание на тип ссылки и тип экземпляра!
Я думаю, что этот ответ лучший: (благодаря Джону Скиту)
// I'd still declare `item` as late as possible, i.e. here rather than
// outside the `try` block, unless you *also* need it outside the try block...
Item item;
if (rs.getString("type").equals("weapon")) {
Weapon weapon = new Weapon();
weapon.setDamage();
item = weapon;
} else {
Armor armor = new Armor();
armor.setDefense();
item = armor;
}
// Other code using `item` here