Почему Java не понимает класс объекта, который я поместил в этот многомерный массив? - PullRequest
1 голос
/ 23 марта 2019

Я работаю над небольшой игрой, но в качестве примера я буду использовать объекты из гипотетического класса Student и объекты из гипотетического класса Books.

У меня есть многомерная сетка, которую я хочу заполнитьили объектами ученика или объектами книги.Может быть, он называется

classroom[][] 

и имеет четыре стола:

[0][0], [0][1], [1][0], and [1][1].

Я хочу, чтобы я мог разместить ученика или книгу (никогда оба) и печатать

classroom[0][1].someStudentAttribute 

если я знаю, что это студент, или

 classroom[0][1].someBookAttribute 

, если я знаю, что это книга.

Чтобы быть ясным, это будет очевидно, когда он будет студентом.или книга.Мне не понадобится надежный способ различения, то есть я буду использовать «.someStudentAttribute» только в ситуации, когда в коде определенно учится студент.

Я где-то читалздесь я могу создать многомерный массив, который принимает много типов объектов, объявив переменную типа Object [] [] перед именем.

Student alice = new Student("alice", 10);
Student bob = new Student("bob", 11);
Student charlie = new Student("charlie", 10);
Book mathBook = new Book("mathematics", 578);

Object[][] classroom = new Object[2][2];
classroom[0][0] = alice;
classroom[0][1] = bob;
classroom[1][0] = charlie;
classroom[1][1] = mathBook;

Это возвращает соответствующий класс (ученик класса)

System.out.println(classroom[0][0].getClass());

Это также возвращает правильный класс (книгу классов)

System.out.println(classroom[1][1].getClass()):

Но как только я пытаюсь напечатать атрибут, я получаю ошибку:

System.out.println(classroom[0][0].age);

Ошибкаis:

java: cannot find symbol
symbol: variable age
location: java.lang.Object

Похоже, Java забыл, что

classroom[0][0] 

принадлежит классу ученика, как только я спрашиваю его для атрибута!Если

classroom[0][0] 

не является правильным способом представления объекта в этом слоте массива, что это такое?

Может быть как-то связано с объявлением переменной как Object [] [], но опять же, дело в том, чтобы иметь возможность помещать объекты из разных классов внутрь.Если бы я просто назвал это студентом [] [], я бы не смог положить в книги.

Ответы [ 2 ]

3 голосов
/ 23 марта 2019

Тип класса объекта classroom равен Object, и при вызове classroom[0][0].age класс Object не знает атрибутов, определенных вами в вашем собственном пользовательском классе.Вам нужно будет привести ваш classroom[0][0] к вашему собственному классу, например:

if (classroom[0][0] instanceof Student) { // Although it is a bad practice and against OOP
    System.out.println(((Student)classroom[0][0]).age);
}

Я предложу прочитать некоторые вещи о принципах ООП и затем найти правильное решение.

Edit: Возможно, я не совсем понимаю, чего вы должны пытаться достичь, но вот пример реализации, который может дать вам некоторое представление.В общем, избегайте прямого доступа к переменной, используя объект, скорее используйте getter / setter.

Проверьте этот пример реализации.

public class Classroom {

    enum ClassRoomObjectType {
        STUDENT,BOOK;
    }

    static abstract class ClassRoomObject {
        private String name;
        private int age;
        private ClassRoomObjectType classRoomObjectType;

        protected ClassRoomObject(ClassRoomObjectType classRoomObjectType, String name, int age) {
            this.classRoomObjectType = classRoomObjectType;
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return String.format("Type: %s, Name: %s, Age: %s", classRoomObjectType, name, age);
        }
    }

    static class Student extends ClassRoomObject {

        public Student(String name, int age) {
            super(ClassRoomObjectType.STUDENT, name, age);
        }

    }

    static class Book extends ClassRoomObject {

        public Book(String name, int age) {
            super(ClassRoomObjectType.BOOK, name, age);
        }

    }

    public static void main(String[] args) {
        Student alice = new Student("alice", 10);
        Student bob = new Student("bob", 11);
        Student charlie = new Student("charlie", 10);
        Book mathBook = new Book("mathematics", 578);

        ClassRoomObject[][] classRoomObjects = new ClassRoomObject[2][2];
        classRoomObjects[0][0] = alice;
        classRoomObjects[0][1] = bob;
        classRoomObjects[1][0] = charlie;
        classRoomObjects[1][1] = mathBook;

        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                System.out.println(classRoomObjects[i][j]); // This is how you can print the object content by overriding toString method
                System.out.println(classRoomObjects[i][j].getAge()); // This is how you should access the value of an object attribute by using getters and not directly the variable
            }
        }
    }

}
1 голос
/ 23 марта 2019

Java - это так называемый статически типизированный язык, в отличие от, скажем, Javascript, который динамически типизирован.Это означает, что этот тип каждого выражения должен быть известен во время компиляции в Java.Как только classroom объявлено как Object[][], выражение classroom[0][0] имеет тип Object, и этот тип не имеет поля age.Вам необходимо либо явным образом привести выражение к Student, например:

if (classroom[0][0] instanceof Student)
    System.out.println(((Student)classroom[0][0]).age);

, либо изменить тип элементов класса на что-либо с атрибутом age.

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

class ClassroomObject {
    // Common stuff
    public int age;
}

class Book extends ClassroomObject {
    // Book-specific stuff
}

class Student extends ClassroomObject {
    // Student-specific stuff
}

ClassroomObject [][] classroom;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...