Как избежать instanceof в поисковых программах? - PullRequest
1 голос
/ 14 июня 2019

В настоящее время я выполняю линейный поиск по списку элементов, например, так:

private Item getKey(ArrayList<Item> inventory) {
    for(Item item : inventory) {
        if(item instanceof Key) {
            return item;
        }
    }
    return null;
}

Я слышал, что для использования instanceof считается "запахом кода".Обычно, чтобы избежать использования instanceof, я бы использовал полиморфизм (например, то, что описано в этом ответе ), однако в таком случае я изо всех сил пытаюсь понять, как я мог бы это использовать.

Поэтому мне интересно, есть ли способ, которым я мог бы устранить необходимость instanceof и, возможно, использовать другую технику, такую ​​как полиморфизм, которая более сфокусирована на OOD?

Ответы [ 2 ]

1 голос
/ 20 июня 2019

Если вам нужно решение, которое использует полиморфизм вместо instanceof, вам нужно определить метод isKey() в своем супертипе и переопределить его для подтипов, которые квалифицируются как ключи:

public class Item {

    public boolean isKey() { 
        return false; 
    }
}

class Key extends Item {
    @Override
    public boolean isKey() {
        return true;
    }
}

Тогда ваше решение становится:

private Item getKey(ArrayList<Item> inventory) {
    for(Item item : inventory) {
        if(item.isKey()) {
            return item;
        }
    }
    return null;
}

Обратите внимание, что это вернет ключ first в вашем инвентаре.

Для более современного (и компактного) стиля кода вы можете использовать метод предиката isKey() в операции stream и возвращать Optional вместо, возможно, нулевого значения ключ:

private Optional<Item> getKey(ArrayList<Item> inventory) {
    return inventory.stream().filter( item -> item.isKey() ).findFirst();
}
1 голос
/ 14 июня 2019

Ваш случай отличается от вашей ссылки. Я не думаю, что ваш код в этом случае является «запахом кода».
Как @shmosel упоминает

Недостаток не в этом методе.

Но вы можете сделать свой код более пригодным для повторного использования, как:

private Item getKey(ArrayList<Item> inventory) {
    return getAnItemByType(inventory, Key.class);
}
private Item getAnItemByType(ArrayList<Item> inventory, Class<? extends Item> type) {
    for(Item item : inventory) {
        if(type.isInstance(item)) {
            return item;
        }
    }
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...