2015-03-14 2 views
0

Предположим, что у меня есть суперкласс под названием animal и три подкласса, соответственно называемые Dog, Cat и Lion, которые расширяют класс animal. Затем я создаю объект каждый для подкласса и добавляю его в ArrayList<animal>.Как определить тип производного класса?

Когда я прохожу через этот список, как я могу отличить Dog или Cat объекта, каждый объект в ArrayList имеет тип animal?

+2

Почему вы должны их отличить на самом деле? как правило, если вы серьезно хотите изучить некоторые проблемы, вам нужно понять динамическую отправку. – HuStmpHrrr

+0

Я пытаюсь tokenize ввод строки. Мой суперкласс - это токен, а его подклассы: круглые скобки, число, оператор. Я положил их в арраиста. Мне нужно различать их, чтобы выполнять определенную функцию, основанную на их типе. Это их другой способ (лучший способ?), Чем использовать instanceOf для этого случая? –

+1

Но разве они не выполняют одно и то же действие; 'apply()' например? Затем вы переопределяете применение в каждом подклассе и просто вызываете 'theThing.apply()'. Он применяет его надлежащим образом на основе конкретного типа экземпляра. – ChiefTwoPencils

ответ

4

Вы должны использовать instanceof оператор:

if (animal instanceof Dog) { 
    //something 
} else if (animal instanceof Cat) { 
    //something 
} else if (animal instanceof Lion) { 
    //something 
} 

Однако, вы должны подумать дважды, если вам действительно нужно, чтобы использовать его. В большинстве случаев instanceof - это плохая практика ООП.

+0

Большое спасибо! Я смотрел каждый, где было решение, но не мог найти правильные слова. Благодаря! –

+0

http://stackoverflow.com/questions/2750714/is-instanceof-considered-bad-practice-if-so-under-what-circumstances-is-instan – migron

+0

Практика Bad OOP, как уже объяснялось в комментариях. – m0skit0

3

Пункт наследования состоит в том, что вам не нужно знать, какой тип животного каждый объект, когда вы вызываете метод, который имеет объект животного, тогда каждый субкласс может реализовать этот метод по своему усмотрению.

Если вы все равно должны знать, что тип вы можете использовать ключевое слово InstanceOf, но если вам нужно использовать это, вероятно, вы сделали что-то неправильно, как объектно-ориентированное программирование программируют

+0

Вы уверены? Иногда это полезно: мне нужно переместить все перемещаемые объекты в свой список перемещаемых объектов и нарисовать только те объекты, которые также доступны для рисования ... Я не думаю, что мне нужно было бы сохранить два списка. – vojta

+1

@vojta, как вы сказали, иногда oop действительно противостоят интуитивному. но, к сожалению, реальный oop не нуждается в 'instanceof'. – HuStmpHrrr

+1

@vojta, я думаю, проблема с этим - SoC. Перемещение и живопись на самом деле не связаны. Таким образом, должно быть разделение между движением предметов и живописью. Выбор списка - это действительно большая проблема. Если у вас есть все движимые вещи, но только некоторые рисунки, возможно, карта списков - лучший вариант. Таким образом, вы можете получить лакокрасочные материалы, когда это необходимо. – ChiefTwoPencils

0

В Java вы должны использовать InstanceOf. Вы обнаружите, что люди препятствуют использованию экземпляра. Большинство людей считают это запахом кода. Зачем? Потому что вся причина использовать систему набора текста заключается в том, что вы можете обрабатывать разные типы, как если бы они были одинаковыми. Таким образом, другими словами, если вы собираете кучу разных типов, основываясь на том, что они имеют сходство, воплощенное в вашем базовом классе, вы должны быть довольны доступом к каждой из этих ссылок базового класса. Если вы пишете код, проверяющий каждый тип, а затем делаете разные вещи, это означает, что ваша система типов протекает.

Например, рассмотрите некоторые операции, которые вы, возможно, захотите выполнить. Возможно, вам нужно кормить каждого животного (в спасательном центре). Вы бы определили операцию в базовом классе, например, «любит есть», что указывает на то, что хочет это животное. Каждый подкласс обеспечивал бы собственную реализацию этого метода. Но из вашего основного кода вы можете просто перебирать коллекцию и вызывать метод из базового класса, не зная подробностей каждого из них. В этом случае ваша модель предоставила расширение. Помните поговорку: открытую для расширения, закрытую для модификации (приписывается Бертран Мейеру).

Если вы просто бросили кучу связанных объектов в коллекцию и решите: «Хорошо, я пойму, что делать с каждым, учитывая обстоятельства, которые я нахожу», тогда вы не следуете этому принципу.

-1

Использование InstanceOf дифференцироваться между различными типами объектов в иерархии классов

import java.util.ArrayList; 
import java.util.List; 

public class Inheritance { 
    public static void main(String[] args) { 
     //create a list to hold all animals 
     List<Animal> animals = new ArrayList<Animal>(); 

     //add animals 
     animals.add(new Animal()); 
     animals.add(new Dog()); 
     animals.add(new Cat()); 

     for (Animal a:animals) { 

      //Use instanceof to determine type of object 

      if(a instanceof Dog){ 
       Dog dog = (Dog)a; 
       dog.displayDog(); 
      }else if (a instanceof Cat) { 
       Cat cat = (Cat)a; 
       cat.displayCat(); 
      }else{ 
       a.display(); 
      } 
     } 


    } 

} 

class Animal{ 
    public void display(){ 
     System.out.println("This is a Animal"); 
    } 
} 

class Dog extends Animal{ 
    public void displayDog(){ 
     System.out.println("This is a Dog"); 
    } 
} 

class Cat extends Animal{ 
    public void displayCat(){ 
     System.out.println("This is a Cat"); 
    } 
} 
+2

К сожалению, это * все * плохо. Во-первых, наивно использовать методы displaySpecificType. Это идет вразрез со всем ценным в ООП. В разработке таких классов нет никакой пользы. Вы хотите, чтобы иметь возможность делать «animal.display()» в * all * случаях и ожидать, что дисплей будет отображать данный тип. – ChiefTwoPencils

1

Что Chief Два Пучков пытаются сказать в своих комментариях, что вы можете использовать instanceof, но в вашей ситуации есть намного лучше ООП шаблон проектирования, который будет использоваться. Например, вместо того, чтобы различать тип объекта, почему бы вам просто не использовать базовый метод в Animal и переопределить в каждом подтипе? Например, apply. Таким образом вы можете просто позвонить animal.apply() и применить правильный метод для этого типа.

Вот пример того, что он имеет в виду:

import java.util.ArrayList; 
import java.util.List; 

abstract class Animal { 
    abstract void apply(); 
} 

class Dog extends Animal { 

    @Override 
    void apply() { 
     System.out.println("Bark bark!"); 
    } 
} 

class Cat extends Animal { 

    @Override 
    void apply() { 
     System.out.println("Meeeeeow!"); 
    } 
} 

class Lion extends Animal { 

    @Override 
    void apply() { 
     System.out.println("Rrrrrroar"); 
    } 
} 

public class Main { 
    public static void main(final String[] args) { 
     final List<Animal> animals = new ArrayList<>(); 
     animals.add(new Dog()); 
     animals.add(new Cat()); 
     animals.add(new Lion()); 

     // Dog 
     animals.get(0).apply(); 
     // Cat 
     animals.get(1).apply(); 
     // Lion 
     animals.get(2).apply(); 
    } 
} 

Как вы можете видеть, мне не нужно, чтобы проверить, какой тип его для правильного поведения, которая будет вызвана для каждого животного. Это и есть полиморфизм.

+0

Это ожидает, что нет специальных аргументов, которые мне нужно передать этому действию. Что, если у меня есть список животных, и мне нужно поставить всех Львов в какой-то гипотетический контейнер «Кейдж», и мне нужно дать «Игрушку» всем собакам? (Предположим, мы никогда не помещаем собак в клетки.) Что мне делать? Я не могу иметь 'lion.putMeIntoCage (cage)' в 'lion.apply()', потому что это не имело смысла (помещать в клетку не метод льва. Класс Lion не знает, что такой класс Cage вообще отсутствует), и у меня не может быть 'dog.playWithToy (toy)', потому что ваш метод 'apply()' не имеет аргументов. – vojta

+0

Сохранение нескольких списков в моем предыдущем комментарии не является решением. Список животных может быть передан некоторым вызывающим классом в качестве аргумента: например, «zoo.welcomeNewAnimals (животные)». Любая идея, как решить это без 'instanceof'? – vojta

+0

Я не буду обсуждать * что, если *, потому что это не так.Есть гораздо больше случаев, когда нельзя использовать 'instanceof', чем использовать его. ** В большинстве случаев ** вам не нужно использовать 'instanceof', но иногда это единственное решение. Он существует по какой-либо причине (так же, как 'goto' существует в C). Просто убедитесь, что это не проблема дизайна. – m0skit0

Смежные вопросы