200 likes | 315 Views
CS 177 Week 11 Recitation Slides. Class Design/Custom Classes. Announcements. Project 4 due 9 pm. Sunday April 4. ANY QUESTIONS?. Class Design Techniques. Reusability: want to create a class that can be useful to programmers over a period of time without making significant changes.
E N D
CS 177 Week 11 Recitation Slides Class Design/Custom Classes
Announcements Project 4 due 9 pm. Sunday April 4
Class Design Techniques • Reusability: want to create a class that can be useful to programmers over a period of time without making significant changes. • Documentation: class should be thoroughly documented to allow users/programmers to know exactly how to use your class without ever seeing your code • “Less is More”: class should be easy to follow and use. Too many methods and variables can be confusing. Try to have as many static and constant members as possible in order to make your class as easy to use as possible • Future Proof: designing a class that can be useful in an unpredictable future can be difficult. Design the class to be flexible to allow for easy updates as technology advances • Privacy: Try to hide as much data as possible (i.e. private members) to prevent corruption
Class Variables • Remember all classes have properties and methods. • The properties and methods that makeup a class are called members of the class • By default, members are associated with the object created as an instance of the class, but not the class itself • To create members that are directly associated with the class, use the static keyword. These members are also known as class variables.
Static Members • Remember: static members can be accessed by static and regular methods, but non-static members cannot be accessed by static methods. • Static members can be either public or private like non-static members • How can you tell a static member by looking at the code? Give some examples of static members you’ve used so far in the course. • Math.random(), Math.cos() • System.out.print() • StdIn.readInt()
public class Item { private static int count = 0; private String name; public Item(String s) { name = s; count++; } public String getName() { return name; } public static int getItemsInUnviverse() { return count; } } public class Static { public static void main(String args[]) { Item item1 = new Item("book"); System.out.println("Name of item1: " + item1.getName()); Item item2 = new Item("car"); System.out.println("Name of item2: " + item2.getName()); System.out.println("Total Number of items: " + Item.getItemsInUnviverse()); } } Static.java Example Would it make sense to declare the class member name as static?
What if we attempted this: public class Item { private static int count = 0; private String name; public Item(String s) { name = s; count++; } public String getName() { return name; } public static int getItemsInUnviverse() { System.out.println("Current name is " + name); return count; } } Why would this code result in a compile time error? A static method cannot access a non-static member Static.java Continued
Constants • Used to specify members that will not change after the object has been created • Constants are declared in Java with the final keyword • Constants can only be assigned a value once and will never change afterwards • Static members can also be declared as constant (useful for global data that will never change)
public class Phone { private final String number; private double price; public Phone(String s, double p) { number = s; price = p; } public double getPrice() { return price; } public String changeNumber(String s) { number = s; return number; } } What is wrong with this code? Compile time error because you can’t assign a value to the final variable “number” Constant.java Example
Inheritance In Java • In Java, you can create a subclass that inherits from a superclass • Key idea: children inherit from the parents and parents pass on attributes to children • Child class has access to all of parents members (properties and methods) • Child can have their own members on top of those of the parents (child considered to be a specialized version of the parent) • Inheritance is an important mechanism of code reuse • The protected keyword is used to protect class members across all inherited classes as well. In other words, protected members are “private” to the entire family of classes.
Overriding Methods In Java • Overriding a method describes when a child class has a member method that has the same name, number of parameters, and type of each parameter as the parent method. However, the body of the method may be different. • In these cases, the child’s version is always used for instances of that child class • Note the move() method in the following examples
Custom Class Example • Now let’s go through a detailed example. I will introduce a family of classes with the Animal class being the parent. • Feel free to make changes along the way to ensure the concepts are clear
public class Animal { protected double weight; protected static int count; protected final boolean carnivore; protected String location; public Animal(double w, boolean c, String l) { weight = w; carnivore = c; location = l; count++; } public double getWeight() { return weight; } public boolean isCarnivore() { return carnivore; } public String getLocation() { return location; } public static int getAnimalPopulation() { return count; } public static void move() { System.out.println("I am an animal that is moving"); } } The Animal.java class is our parent class. Thus, it doesn’t extend any other classes Note the protected declaration for its members. These members need to be accessible from the child classes. Note that the move function is a static function. Why does this make sense? Animal.java Class
public class Fish extends Animal { protected int numFins; protected String type; public Fish(double w, boolean c, int nf, String t) { super(w, c, "ocean"); numFins = nf; type = t; } public int getNumFins() { return numFins; } public String getType() { return type; } public static void move() { System.out.println("I am a fish that swims"); } } Note that the super keyword is used to reference the parent constructor. The unique members, numFins and type, are defined outside of the super constructor. Why is it not necessary to increase the static count variable within the Fish constructor? Notice that the move() method is being overridden. For any Fish object, this is the version that will be used Fish.java SubClass
public class JellyFish extends Fish { protected String color; public JellyFish(double w, boolean c, int nf, String t, String col) { super(w, c, nf, t); color = col; } public String getColor() { return color; } public static void move() { System.out.println("\nI am jellyfish and move gracefully!"); } public static void attack() { System.out.println("You just got stung by a jellyfish!!"); } } Notice the new method attack() on the bottom. Why does it makes sense for this method to be static as well? JellyFish.java SubClass
public class StarFish extends Fish { protected int numArms; public StarFish(double w, boolean c, String t) { super(w, c, 0, t); numArms = 5; } public int getNumArms() { return numArms; } public static void move() { System.out.println("\nI am starfish. I can't move!"); } public void loseArm() { if(numArms > 0) { numArms--; System.out.println("OH NO! You lost an arm!"); } } } Here we see a constant member numArms. It is assigned a value only once in the constructor for this subclass loseArm() subtracts an arm if the StarFish still has one StarFish.java SubClass
public class Inheritance { public static void main(String args[]) { Animal lion = new Animal(300, true, "grasslands"); System.out.print("Characteristics of a lion: \n"); System.out.println("Weight: " + lion.getWeight()); System.out.println("Carnivore: " + lion.isCarnivore()); System.out.println("Location: " + lion.getLocation()); Fish shark = new Fish(800, true, 1, "shark"); System.out.print("\nCharacteristics of a shark: \n"); System.out.println("Weight: " + shark.getWeight()); System.out.println("Carnivore: " + shark.isCarnivore()); System.out.println("Location: " + shark.getLocation()); System.out.println("Number of Fins: " + shark.getNumFins()); System.out.println("Type: " + shark.getType()); StarFish.Move(); JellyFish.Move(); JellyFish.Attack(); StarFish superstar = new StarFish(10, false, "starfish"); System.out.print("\nUnique Characteristics of a starfish: \n"); System.out.println("Carnivore: " + superstar.isCarnivore()); System.out.println("Number of Fins: " + superstar.getNumFins()); System.out.println("Number of arms: " + superstar.getNumArms()); System.out.println("\nTotal population of animals: " + Animal.getAnimalPopulation()); } } Notice how we called our static methods move() and attack(). There are no JellyFish or StarFish objects at this point How many animals would have been counted if we included the count++ code in all of the constructors? 6 Inheritance.java Example
Output from Inheritance.java • Characteristics of a lion: • Weight: 300.0 • Carnivore: true • Location: grasslands • Characteristics of a shark: • Weight: 800.0 • Carnivore: true • Location: ocean • Number of Fins: 1 • Type: shark • I am starfish. I can't move! • I am jellyfish and move gracefully! • You just got stung by a jellyfish!! • OH NO! You lost an arm! • Unique Characteristics of a starfish: • Carnivore: false • Number of Fins: 0 • Number of arms: 4 • OH NO! You lost an arm! • Number of arms:3 • Total population of animals: 3