'Trying to understand Abstract class inheritance and subclass object comparison

I'm working on a project for my data structures class and I've been having a hard time wrapping my head around Abstract class inheritance and how it can be manipulated through subclasses, object comparison, method args, etc. I've been reading through Stack Overflow posts and Java tutorials, and while I've learned a ton, I'm still not understanding some things. I haven't coded in Java in 2+ years and have been using mostly C lately so I'm feeling very rusty and overwhelmed.

Project Overview

I was asked to build a database of sorts that represents data for my university students and professors. I have an abstract superclass, Person, which has 2 child classes Student and Instructor. Lastly (the class I'm currently working on), is a class called UniversityPeople which references an array of Student[] objects as well as an array of Instructor[] objects. The UniversityPeople class has methods to add(), delete(), search(), validate data, ect. for the 2 object arrays.

I know this implementation seems really strange, but I have to follow the instructions unfortunately. I've tried to make the methods work with both arrays seamlessly which is partially where I'm getting confused. Here are my questions:

1.) This is kind of a general question, but one I feel is important to understanding inheritance. I've done tons of reading on this, but I'm still pretty confused. If I create an object that uses the type of the superclass but is a subclass object, like: Person newStudent = new Student(), will this object have access to the methods in it's own class, or is it restricted to the superclass methods only? My understanding was, if the superclass is abstract, the children still inherit their methods when instantiated in this way.

2.) I don't understand how to differentiate between the two object arrays in the methods. For example, I'm writing a clear() function that sets the specified object array(Student[] or Instructor[]) to null when called. I first tried using the instanceOf method to test what type the array was but the compiler warned me I couldn't cast type Student to Person or something like that. Here is the constructor for the class as well as the clear function I'm having trouble with. I'm not sure if I'm understanding how inheritance fully works here, so if there's a better way please enlighten me:

Constructor:

//Global declarations
    //Declares arrays of student and instructor classes
    private Student[] studentArray;
    private Instructor[] instArray;
    private int studentCount;
    private int instCount;

        /*
        checks user input. If user enters 1, create student array.
        if user enters 2, create Instructor array
        */
        public UniversityPeople(int type, int size)
        {
            if (type == 1)
            {
                studentArray = new Student[size];
            }
            else if (type == 2)
            {
                instArray = new Instructor[size];
            }
        }

Separate insert methods for students/instructors because I couldn't figure out a way to do 1, if it's even possible:

 /*
    checks if array is full or duplcate id exists.
    If not, new Student object is created and
    inserted into the student array
    */
    public void insertStudent(String lastName, String firstName, int id,
                              int age, String yearStanding, double GPA)
    {
        boolean checkFull = isFull();
        boolean checkId = containsID(studentArray, id);

        if (checkFull)
        {
            System.out.println("Array is full. Please delete a data member.");
        }
        else if (checkId)
        {
            System.out.println("Duplicate ID. Please check data and re-enter.");
        }
        if (!checkFull && !checkId)
        {
            Student newStudent = new Student(lastName, firstName, id, age, yearStanding, GPA);
            newStudent = studentArray[studentCount];
            studentCount++;
        }
        else
            System.err.println("There was an error while attempting to \n" +
                               "process your request. Please check your \n" +
                               "data entry and try again.");

    }//end insertStudent

    /*
    checks if array is full or duplicate id exists.
    If not, new Instructor object is created and
    inserted into instructor array
    */
    public void insertInstructor (String lastName, String firstName, int id,
                                  int age, int officeNum, String subjectTaught)
    {
        boolean checkFull = isFull();
        boolean checkId = containsID(instArray, id);

        if (checkFull)
        {
            System.out.println("Array is full. Please delete a data member.");
        }
        else if (checkId)
        {
            System.out.println("Duplicate ID. Please check data and re-enter.");
        }
        if (!checkFull && !checkId)
        {
            Instructor newInstructor =
                            new Instructor(lastName, firstName, id, age, officeNum, subjectTaught);
            newInstructor = instArray[instCount];
            instCount++;
        }
        else
            System.err.println("There was an error while attempting to \n" +
                               "process your request. Please check your \n" +
                               "data entry and try again.");

    }//end insertInstructor

Lastly, a method to find someone in the array from their id and a method to clear whatever array is specified. I've made the arg type Person[] array in most of these methods which I hope is acceptable.

public int findPerson(Person[] array, int id)
    {
        for (int i = 0; i < array.length; i++)
        {
            if (array[i].getId() == id)
            {
                return i;
            }
        }

        return -1;
    }

    //Sets specified array to null. I need to reset the count of objects in
    //the specified array to 0, but i'm really confused about how that works. Below is the best
    //understanding I could come up with
    public void clear(Person[] array)
    {
        for (int i = 0; i < array.length; i++)
        {
            array[i] = null;
        }

        if (array.getClass().equals(Student.class))
        {
            studentCount = 0;
        }
        else if (array.getClass().equals(Instructor.class))
        {
            instCount = 0;
        }
        else
        {
            System.out.println("There was an issue validating the object type.");
        }
    }

I'm especially confused about the implementation of the clear() method as I've never had to do this type of object comparison before. I'm not sure why the instanceOf operator comparison was giving me weird results.



Solution 1:[1]

[...] will this object have access to the methods in it's own class, or is it restricted to the superclass methods only? My understanding was, if the superclass is abstract, the children still inherit their methods when instantiated in this way.

It doesn't matter, whether the superclass is abstract. A child class inherits the parent class' methods and attributes. Whether these are accessible by the child class depends on visibility modifiers.

I'm having a hard time understanding how to differentiate between the two object arrays in the methods. For example, i'm writing a clear() function that sets the specified object array(Student[] or Instructor[]) to null when called.

You could overload the clear() method like:

public void clear(Student[] array) {...}
public void clear(Instructor[] array) {...}

or (if I understand the purpose of your example correctly) compare the input array's reference with the array references in your class definition:

public void clear(Person[] array) {
    if(array == this.studentArray) {
        // clear students
    } else if(array == this.instArray) {
        // clear instructors
    }
}

But if you want to actually compare the arrays' types, you can do:

array.getClass().equals(Student[].class)

or

array instanceof Student[]

Solution 2:[2]

For the clear method :

array = new Person[array.length] // re-init arrayt ot it's inital size.
studentCount = studentArrayl.length;
instCount = instArray.length;

that should réinit the given array to a new empty array of the correct length and reasigne correct number to studentCount and instCount.

Regards.

Nemesis.

Solution 3:[3]

For #1, yes, newStudent will have access to it's own methods and also it's superclass unless it's @Overriden.

For #2, you are having a hard time because your UniversityPeople class is doing too many things. This is will become a maintenance issue and is a code smell. UniversityPeople violates the single responsibility principle. Your class should do one thing only. Why not do a UniversityInstructor and a UniveristyStudent? But since you are following instructions, here's an idea for your clear function. Before you null your array, get one content in the array. Say Person person = array[0];, then you can do an if (person instanceof Student) and then if (person instanceof Instructor). This way you'll know the type of you array and proceed accordingly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SME_Dev
Solution 2 Nemesis
Solution 3 jpllosa