620 likes | 750 Views
Object-Oriented Design and Programming (Java). Topics Covered Today. 2.3 Advanced Class Design 2.3.1 Abstract Classes ( 抽象类 ) 2.3.2 Polymorphism ( 多态 ) 2.3.3 Interfaces( 接口 ). Abstract Method. Definition: Methods that do not have implementation (body)
E N D
Topics Covered Today • 2.3 Advanced Class Design • 2.3.1 Abstract Classes (抽象类) • 2.3.2 Polymorphism (多态) • 2.3.3 Interfaces(接口)
Abstract Method • Definition: • Methods that do not have implementation (body) • To create an abstract method, just write the method declaration without the body and use the abstract keyword • No { } • For example, // Note that there is no body public abstract void eat(int amount); public abstract void sleep(int hours);
Abstract Class. • Definition: An abstract class is a class that contains one or more abstract methods • Any class which contains an abstract method must itself be declared abstract. • An abstract class is denoted by using the abstractmodifier • public abstract class ClassName { . . . }
Abstract Class.. • An abstract class cannot instantiated • No instance of an abstract class can be created. // You will get a compile error on the following code MyAbstractClass a1 = new MyAbstractClass(); • If a subclass of an abstract class does not implement all abstract methods inherited from its parent, the subclass must also be defined as abstract.
Example • Consider a chemical company that transports its products in two kinds of containers: wagons and tanks:
Container +computeVolume() : double Wagon Tank -width : double -height : double -length : double -radius : double -length : double +computeVolume() : double +computeVolume() : double Class Diagram
Class Container public abstract class Container { /** * Computes the volume of this container. * @return the volume of this container. */ public abstract double computeVolume(); }
Class Wagon public class Wagon extends Container { private double width; private double height; private double length; public Wagon(double initialWidth, double initialHeight, double initialLength) { width = initialWidth; height = initialHeight; length = initialLength; } public double computeVolume() { return width * height * length; } }
Class Tank public class Tank extends Container { private double radius; private double length; public Tank(double initialRadius, double initialLength) { radius = initialRadius; length = initialLength; } public double computeVolume() { return Math.PI * radius * radius * length; } }
Person -name : String +getName() : String Employee Client -age : int -credit : double +getAge() : int +getCredit() : double Business System
Class Person public abstract class Person { private String name; public Person(String initialName) { name = initialName; } public String getName() { return name; } } Class can be defined as abstract but it does not contain any abstract methods.
Class Employee public class Employee extends Person { private int age; public Employee(String initialName, int initialAge) { super(initialName); age = initialAge; } public int getAge() { return age; } }
Class Client public class Client extends Person { private double credit; public Client(String initialName, double initialCredit) { super(initialName); credit = initialCredit; } public double getCredit() { return credit; } }
Using Person、Employee & Client • No instances of class Person can be created because Person is abstract • Person person = new Person(); • Instances of class Employee and Client can be created because they are concrete classes(实体类) • Employee employee = new Employee("John", 21); • Client client = new Client("Mary", 6000.0); X
When to use Abstract Methods & Abstract Class? • Abstract methods are usually declared where two or more subclasses are expected to fulfill a similar role in different ways through different implementations • These subclasses extend the same Abstract class and provide different implementations for the abstract methods
Abstract Class Summary • For some applications we might want a generic base class that we will never instantiate. • Note that if any method is declared abstract, the class must be declared abstract as well or the compiler will give an error message. • An abstract class can include concrete methods and fields. • In fact, an abstract class does not need to include any abstract methods.. • Note that an abstract method has no code body, no braces {}. • All of the abstract methods must be overridden by methods in the concrete subclasses.
Topics Covered Today • 2.3 Advanced Class Design • 2.3.1 Abstract Classes (抽象类) • 2.3.2 Polymorphism (多态) • 2.3.3 Interfaces(接口)
Upcasting Again public class CellPhone { CellPhone() { //…} public void ring(Tune t) { t.play(); } } public class Tune { public void play() { System.out.println("Tune.play()"); } } public class ObnoxiousTune extends Tune{ ObnoxiousTune() { // …} // … }
Tune A “UML” diagram ObnoxiousTune An ObnoxiousTune “is-a” Tune public class CellPhoneDemo { public static void main(String[] args) { CellPhone noiseMaker = new CellPhone(); ObnoxiousTune ot = new ObnoxiousTune(); noiseMaker.ring(ot); // ot works though Tune called for } }
Aspects of Upcasting • Upcasting is a cast • The exact type of the object is lost • What gets printed in the CellPhone example? • Tune.play() (what were you expecting?) • Is this “the right thing to do”? • The alternative: write separate play() methods for each subclass of Tune?
A little Improvement • class CellPhone { • CellPhone() { //…} • public void ring(Tune t) { t.play(); } • } • class Tune { • Tune() { //…} • public void play() { • System.out.println("Tune.play()"); • } • } • class ObnoxiousTune extends Tune{ • ObnoxiousTune() { // …} • public void play() { • System.out.println("ObnoxiousTune.play()"); • } • }
Tune +play() ObnoxiousTune +play() What Gets Printed Now? public class CellPhoneDemo { public static void main(String[] args) { CellPhone noiseMaker = new CellPhone(); ObnoxiousTune ot = new ObnoxiousTune(); noiseMaker.ring(ot); // ot works though Tune called for } }
Polymorphism • The second example prints ObnoxiousTune.play() • Since an ObnoxiousTune object was sent to ring(), the ObnoxiousTune’s play() method is called. • Definition • Through inheritance, a class can be used as more than one type; it can be used as its own type, any base types, or any interface type if it implements interfaces. This is called polymorphism.
Method-Call Binding • The correct method is attached (“bound”) to the call at runtime. • The runtime system discovers the type of object sent to ring(), and then selects the appropriate play() method: • if it’s a Tune object, Tune’s play() is called • if it’s an ObnoxiousTune object, ObnoxiousTune’s play() is called
Is Java Always Late-Binding? • Yes, always, except for final methods. • final methods can’t be overridden, so the compiler knows to bind it. • The compiler may be able to do some speed optimizations for a final method. • In C++, binding is always at compile-time, unless the programmer says otherwise.
Another Polymorphism Example public static void main(String[] args) { CellPhone noiseMaker = new CellPhone(); Tune t; double d = Math.random(); if (d > 0.5) t = new Tune(); else t = new ObnoxiousTune(); noiseMaker.ring(t); }
References and Subclasses • A Tune reference can refer to an ObnoxiousTune object. • This doesn’t work the other way around: any old Tune may not be an ObnoxiousTune. • So, an ObnoxiousTune reference cannot refer to a Tune object.
Let’s Fool the Compiler! public static void main(String[] args) { CellPhone noiseMaker = new CellPhone(); Tune t1 = new Tune(); Tune t2 = new ObnoxiousTune(); noiseMaker.ring(t1); noiseMaker.ring((Tune)t2); } Nothing changes… ObnoxiousTune.play() is still printed.
Let’s Fool the Compiler! public static void main(String[] args) { CellPhone noiseMaker = new CellPhone(); Tune t1 = new Tune(); Tune t2 = new ObnoxiousTune(); noiseMaker.ring(t1); noiseMaker.ring((ObnoxiousTune) t2); } Nothing changes…
Let’s Fool the Compiler! public static void main(String[ ] args) { CellPhone noiseMaker = new CellPhone(); Tune t1 = new Tune(); Tune t2 = new ObnoxiousTune(); noiseMaker.ring((ObnoxiousTune) t1); noiseMaker.ring(t2); } This compiles, but gets a CastClassException at runtime (even though Tune has a play() method). “Downcasting” can be dangerous!
Container +computeVolume() : double Wagon Tank -width : double -height : double -length : double -radius : double -length : double +computeVolume() : double +computeVolume() : double Class Container
Polymorphism • A reference variable can hold a reference to an object of the declared type or any subtype of the declared type (一个引用变量可以引用它所属类型及它的子类的对象) • Container container; • container = new Wagon(1, 1, 3); • container = new Tank(1, 3); • When a polymorphic method is called, the Java Virtual Machine (JVM) determines which version of the method to execute by examining the reference variable used in the method call. • double volume = container.computeVolume();
Example import java.io.*; public class ContainerDemo { private static PrintWriter stdOut = new PrintWriter(System.out, true); public static void main(String[] args) { Container container; container = new Wagon(1, 1, 3); stdOut.println("Volume: " + container.computeVolume()); container = new Tank(1, 3); stdOut.println("Volume: " + container.computeVolume()); } } Volume:3.0 Volume:9.4247777
Method-Call Binding • Static binding • The compiler determines which method implementation to use in advance • 编译时就确定了要调用的方法 • C++ • Dynamic binding(late binding, virtual binding) • The compiler can't determine which method implementation to use in advance • The runtime system (JVM) selects the appropriate method at runtime, based on the class of the object • 在运行阶段才确定要调用的方法 • 是实现多态必不可少 • JAVA • RTTI
Method-Call Binding • The runtime system discovers the type of object sent to computeVolume(): • if it’s a Wagon object, Wagon’s computeVolume() is called • if it’s a Tank object, Tank’s computeVolume() is called
Topics Covered Today • 2.3 Advanced Class Design • 2.3.1 Abstract Classes (抽象类) • 2.3.2 Polymorphism (多态) • 2.3.3 Interfaces(接口)
Interface • An interface is collection of constants and abstract methods. • Syntax: interface interface_name { constant -declarations; abstract methods; }
Example • All methods in an interface are implicitly public and abstract. • All data fields in an interface are implicitly public, static, and final. public interface MyInterface { int CONSTANT = 10; void methodOne(); double methodTwo(); void methodThree(double value); }
Technical Details • Use theinterface keyword rather than class. An Interface usually sits in its own .java file. • Use publicor nothing, private and protected aren’t allowed. • To implement, write a class using the implementskeyword. • Interface methods are always public. • You can inherit from an interface to create a new interface. • A single class can implement several interfaces simultaneously (Java’s version of multiple inheritance).
Interface Implementation public class ClassA implements MyInterface { public void methodOne() { ... } public double methodTwo() { ... } public void methodThree(double value) { ... } }
A Class Implements an Interface • When a class implements an interface, it agrees to implement all methods in the interface. • If the class does not implement all the methods, the class must be defined as abstract.
Inherit form an interface • An interface can extend another interface public interface MyInterface extends InterfaceOne { void aMethod(); }
interface can extend several interfaces public interface MyInterface extends InterfaceOne, InterfaceTwo { void aMethod(); }
A class can implements several interfaces public class ClassA implements Interface1, Interface2, Interface3 { ... }
<<interface>> MyInterface +methodOne() +methodTwo() : double +methodThree(newValue : double) ClassA ClassB +methodOne() +methodTwo() : double +methodThree(newValue : double) +methodOne() +methodTwo() : double +methodThree(newValue : double) UML Representation of Interfaces
<<interface>> Device +turnon() +turnoff() DeviceDemo Stopwatch +turnon() +turnoff() +turnon() +turnoff() Case Study
Interface Device public interface Device { /** * Turns the device off. */ void turnOff(); /** * Turns the device on. */ void turnOn(); }
Class DeviceDemo import java.io.*; public class DeviceDemo implements Device { private static PrintWriter stdOut = new PrintWriter(System.out, true); private String name; public static void main (String[] args) { Device device = new DeviceDemo("demo"); device.turnOn(); device.turnOff(); } public DeviceDemo (String initialName) { name = initialName; } public void turnOff() { stdOut.println("Turn off device " + name); } public void turnOn() { stdOut.println("Turn on device " + name); } }