GWU

CS 1111

Introduction to Software Development

GWU Computer Science


Lecture Notes 09: Classes and Object-Oriented Design


Objectives

By the end of this module, you will be able to:




In the last lecture, we discussed how Java handles memory and scope between variables, methods, and fields (variables declared in a class outside of a method). In this lecture, we'll (finally!) go over classes and show how fields are used to represent object state.

Why are classes and objects useful in computation?

Classes, Objects, and Memory Layout

We have been defining lots of classes all semester -- in fact, to be able to run any code in Java, we need a main method inside of some arbitrary class! However, we were never really using classes so far for their intended purpose: to group related information about some user-defined type (the class) in one place, so that we can operate on that data.

So what is a class? What is an object? You can think of a class as the instructions or blueprint for what we want to store:

What are classes?

So, what are objects?

Classes are frequently used to collect and store data of real-world concepts, entities, and objects. For example, take the example of the Facebook user class:

      public class FacebookUser {
          public long userId = 1;
          public String firstName, 
          public String lastName;
          public FacebookUser[] friends;

          public boolean checkIsFriend(FacebookUser person){
            for(int i = 0; i < friends.length; i++)
              if(friends[i].equals(person))
                return true;
            return false;
          }

          public long getId(){
            return userId;
          }

          public void setId(long idIn){
            userId = idIn;
          }

          //more methods would go below
      }
      

The class gives the blueprint for each object:

Why do we need objects?

What function do objects provide compared to variables, arrays, etc? How do they relate to static variables stored in classes?



Multiple objects exist, each with possibly different sets of data. Objects are allocated with new .

          public static void main(String[] args) {
              FacebookUser user1 = new FacebookUser();
              FacebookUser user2 = new FacebookUser();

              user1.setId(5);
              System.out.println(user1.userId + " " + user2.getId());
          }
      

Activity 1 (1-minutes): What does the above print out? Why?:





Constructors

If a class gives the blueprint to create objects, constructors lay the initial foundation for each object.

Constructors are methods that are invoked when a new object is created that are used to initialize the data of the new object.

FacebookUser u = new FacebookUser();

new FacebookUser(); invokes the constructor on the newly created object.

The constructor can be overloaded just like any other method:

FacebookUser u = new FacebookUser("chester", "thecat");

What does a constructor look like? An example:

      public class FacebookUser {
          private long userId;
          private String firstName, lastName;
          private FBUser[] friends;

          public FacebookUser() {
              // initialize object's data here
          }

          public FacebookUser(String first, String last) {
              firstName = first;
              lastName = last;
          }
          public void setId(long id) {
              userId = id;
          }
          public long getId() {
              return userId;
          }
      }
      

Earlier we saw that we don't have to write a constructor to use one that has no arguments; Java gives you this "for free." Such a constructor will assign all fields their default values (or use how these attributes were initialized). If you start to write your own constructor(s) as above, you will lose the default constructor -- Java's expectation is you know what you're doing and need something more specific than the default behavior.




Accessing an object's member methods and variables

As we saw above (and earlier with Strings), methods in a class can operate on an object using the dot notation. If var is a variable referring to an object,

            var.methodName();
      

invokes the methodName method on var's object.

Read this as "we're invoking the methodName method of the var object"

 

When an object is allocated with new, e.g.:

          A var = new A();
      

 

A slightly more complicated example:

          FacebookUser var1 = new FacebookUser();
          FacebookUser var2 = var1;
          var2.setId(10);
          System.out.println(var1.getId());
      



Activity 3 [Group Work] (5-minutes):
First, add the following methods to the FacebookUser class: Then, write a new class called FBUserTest class, with a main method. Do this in a text editor, since he visualizer can't run multiple files.

Finally, create four FacebookUser objects in FBUserTest, initiallize them all, and populate their friend lists.




public versus private visibility

You might be wondering why bother having getters and setters, when we can access the field directly, as we did above with user1.userId? It turns out that, as good software engineers, we actually want to avoid having people write code like this that allows field access directly, for reasons we will see later this semester.

In Java, we can control what code that is outside of a class is able to see/use. For example, because we defined userId to be public, this meant that anyone can access the field from the object directly with user1.userId. However, we're going to stop this for now, and you'll see almost all examples set fields to private visibility, which doesn't allow this type of access; this is why we're writing getters and setters. Later, we'll see examples of where it makes sense (and good software engineering sense) to use the public visibility.

Note that, so far, all of our methods have public visibility; this will often be the case. You can also specify private methods, which means only other methods in the same class can call them.

We'll run though some examples in a bit. For now, let's get used to the proper idioim of keeping our fields private, writing getters and setters, and having methods be public.

Another example:

      public class ObjExample {
          private int data;
          public void modify(int v) {
              data = v;
          }
          public int access() {
              return data;
          }
          public void addData(ObjExample o) {
              data += o.access();
          }
          public static void main(String[] args) {
              ObjExample v1 = new ObjExample();
              ObjExample v2 = v1;
              v2.modify(10);
              System.out.println(v1.access());

              ObjExample v3 = new ObjExample();
              v3.modify(3);
              v3.addData(v2);
              System.out.println(v3.access());

              v3.addData(v3);  // what's happening here?
              v1.addData(v2);  // ...and here?
          }
      }
      

Activity 4 (1-minutes): What does the above print out? Why?

What are the last two lines doing? Describe them




What about static?

We can now better understand the static keyword, given that we know what a class and objects are now.

The static keyword is used to indicate when a field is meant to be shared amongst all objects of a class, as opposed to each objects having its own values for that field:



An Example with static and non-static variables and methods:

      public class StaticExample {
        private static int staticVar;
        private int objectVar;

        public static void staticSetVar(int val) {
          staticVar = val;
        }
        public static int staticGetVar() {
          return staticVar;
        }

        public void objSetVar(int val) {
          objectVar = val;
        }
        public int objGetVar() {
          return objectVar;
        }
      }
      

      public class TestStaticExample {
        public static void main(String[] args) {
          StaticExample.staticSetVar();
          System.out.println ( StaticExample.staticGetVar() );

          StaticExample ob1 = new StaticExample();
          ob1.objSetVar();
          System.out.println ( ob1.objGetVar() );
        }
      }
      

Visualizing this:



Activity 1 [Group Work] (2-minutes): Compile and Run the following example. What errors do you get? Fix them where possible.

      public class StaticExample2 {
          private static int staticVar;
          private int objectVar;

          public void objSetVars() {
              objectVar = 10;
              staticSetVars();
          }
          public int[] objGetVars() {
              return new int[]{staticvar, objectVar};
          }
          public static void staticSetVars() {
              staticVar = 10;
              objSetVars();
          }
          public static int[] staticGetVars() {
              return new int[]{staticvar, objectVar};
          }
          public static void main(String[] args) {
              staticSetVars();
              objSetVars();

              StaticExample v = new StaticExample();
              v.staticSetVars();
              v.objSetVars();
          }
      }
      




Null Objects

null is a valid value for a variable of any non-primitive type. This includes:



null is simply a reference to nothing; you can think of it as a reference to a "nothing memory address".

      public class NullTest {
          private int n;
          public int getN() {
              return n;
          }
          public static void main(String[] args) {
              NullTest nt = null;
              System.out.println(nt.getN());
          }
      }
      

Activity 2 (2-minutes): Execute this program. What happens when this program is executed? Why?

Activity 3 (2-minutes): What is the default value for variables of a class's type? Write a small program TestDefault.java to print out the default value of the variable: FBUser u;




Classy Scope

Where is the problem in the following code?

      public class FacebookUser {
          private long userId;
          private String firstName, lastName;
          private FacebookUser[] friends;

          public FacebookUser(String firstName, String lastName) {
              // uh oh...
          }
          public void setId(long id) {
              userId = id;
          }
          public long getId() {
              return userId;
          }
      }
      

Scope works the same with all fields and varaibles in methods:

      public class FacebookUser {
          private long userId;
          private String firstName, lastName;
          private FacebookUser[] friends;

          public FacebookUser(String firstName, String lastName) {
              this.firstName = firstName;
              this.lastName = lastName;
          }
          public void setId(long id) {
              userId = id;
          }
          public long getId() {
              return userId;
          }
      }
      

this is, generically, a variable that references the "current" object.




OO Design

Why does Object-Oriented Programming (OOP) exist?

A fundamental goal of object oriented design is reuse.

Next class:

We'll go through some code traces with classes and objects.

Assignments for next lecture:

Look over homework 6, and try it on your own.