Skip to content

Instantly share code, notes, and snippets.

@hschafer
Created January 11, 2019 21:02
Show Gist options
  • Save hschafer/8cad7bbae3e9288e6e4e709affdce01b to your computer and use it in GitHub Desktop.
Save hschafer/8cad7bbae3e9288e6e4e709affdce01b to your computer and use it in GitHub Desktop.

Review

We have learned a lot this week about object-oriented programming:

  • How to define our own classes.
    • How to manage state (fields) and define behaviors (methods) for those classes.
  • How to create instances of the classes we defined.
  • How to create abstractions that separate the client from knowing how our class works internally and how to enforce that the client doesn't get access to our internal representation (private fields).

These are all concepts that can be pretty tricky to wrap your head around the first time you see them since they require a pretty different way to think about the programs than what you are used to.

Double Vision

What if we wanted to write methods for ArrayIntList that took other ArrayIntList instances as parameters? This sounds kind of weird at first but can be really helpful! For example, the ArrayList class has a method addAll that takes another ArrayList and adds all the values in that list to this one. We want to emulate this behavior for ArrayIntList.

We would want to write the client code so it would look something like the following

public class Client {
    public static void main(String[] args) {
        ArrayIntList list1 = new ArrayIntList();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayIntList list2 = new ArrayIntList();
        list2.add(4);
        list2.add(5);

        list1.addAll(list2);

        System.out.println(list1); // Should print [1, 2, 3, 4, 5]
    }
}

We would start by writing a method with the correct header

public class ArrayIntList {
    private int[] elementData;
    private int size;

    // constructors and other methods

    // post: adds all the values from other to the end of this list.
    // the values will appear at the end in the same order they appear in other.
    public void addAll(ArrayIntList other) {
        // TODO implement this method
    }
}

In the addAll method, we would have two variables that refer to different instances of the ArrayIntList class; this would refer to the same list as list1 while other would refer to the same list as list2.

Now we could loop over all the values in other and add them to the contents of our list. A simple way to do this would be

public void addAll(ArrayIntList other) {
    for (int i = 0; i < other.size(); i++) {
        this.add(other.get(i));
    }
}

What this is doing is using the standard traversal over the other ArrayIntList, getting the value at each index, and then calling the add method (that appends at the end) on this ArrayIntList. You are allowed to prepend method calls on yourself with this. to make it clear which ArrayIntList you are calling the method on; this is not required because Java will go in and insert the this. itself (just like it did for accessing fields), but I added it for clarity.

Check your understanding

Try solving this problem on Practice-It!

Some lazy pun about "private"

The addAll code above is actually a working implementation and is totally fine. One other thing I want to mention is an extra thing you can do when you take another instance of your type as a parameter: you are allowed to access its private fields!

Here is the same method implemented by accessing the fields of other directly.

public void addAll(ArrayIntList other) {
    for (int i = 0; i < other.size; i++) {
        this.add(other.elementData[i]);
    }
}

This sounds weird at first since I first said that private means no one outside can access your fields, but Java has a slight technicality to that statement. To Java, private doesn't mean private to things outside this instance, it means private to things outside of this class. While that looks like a tiny wording difference, what it implies is that any instance of ArrayIntList has the ability to access fields of any other ArrayIntList it has a reference to because they are of the same class.

This is definitely different to our human notion of the word "private"! We would think of any private state you have as only accessible only to you, but Java would allow anyone of type Human to access your private fields!

It's rare that you are required to access private fields of other instances of your type, but it's good to know that it is a possibility. As we mentioned in lecture, there is always a trade-off between directly accessing fields and calling methods (fields are generally faster, but accessing methods instead leads to better abstractions and can make your code more flexible) so it's really up to you to figure out what you think is the most readable.


Have any feedback about this reading? Please let us know using this form.

Copyright © 2019 Hunter Schafer and Porter Jones. All rights reserved. Permission is hereby granted to students registered for University of Washington CSE 143 for use solely during Winter Quarter 2019 for purposes of the course. No other use, copying, distribution, or modification is permitted without prior written consent. Copyrights for third-party components of this work must be honored. Instructors interested in reusing these course materials should contact the authors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment