320 likes | 393 Views
Inheritance. Extending Classes. It’s possible to create a class by using another as a starting point i.e. Start with the original class then add methods, change what methods do, etc. Allows reuse Can extend a class in several ways for different purposes … based on the same original code.
E N D
Extending Classes • It’s possible to create a class by using another as a starting point • i.e. Start with the original class then add methods, change what methods do, etc. • Allows reuse • Can extend a class in several ways for different purposes • … based on the same original code
Inheritance • Inheritance allows a software developer to derive a new class from an existing one • The existing class is called the parent class, or superclass, or base class • The derived class is called the child class or subclass • As the name implies, the child inherits characteristics of the parent • That is, the child class inherits the methods and data defined by the parent class
Vehicle Car Inheritance • Inheritance relationships are shown in a UML class diagram using a solid arrow with an unfilled triangular arrowhead pointing to the parent class • Proper inheritance creates an is-a relationship, meaning the child is a more specific version of the parent
Example • In the Blackjack design example, we had a Player class and a Dealer class • similar classes • each has a hand, takes turns,… • We could define a parent class Person that can then be extended to create appropriate subclasses
Inheriting • Suppose we have a simple class A class A { private int count; public int method() { return 1; } } • And we want to define an extended class B with another method…
Inheriting • Now B can inherit A and add a new method: class B extends A { public int newMethod() { return 2; } } • B now has everything from the definitions of both A and B
Inheriting • Using A and B: A myA = new A(); B myB = new B(); System.out.println(myA.method()); System.out.println(myB.method()); System.out.println(myB.newMethod()); • Output: 112 • An instance of B also has all members from A
Parents and Privacy • Subclasses cannot access private members class B extends A {…. public void setCount(int count) { this.count = count; } } • ERROR: count is private in A… this is not A • Just like any other code – can’t access private members • We don’t want count to be public…
The protected Modifier • Encapsulation says that members should not be public… • But we want access to inherited members • New visibibility modifer: protected
The protected Modifier • A protected variable can be accessed from all code in the same package • It provides more encapsulation than public visibility, but is not as tightly encapsulated as private visibility • Key point: Protected variables can be accessed from all subclasses of a given class • In UML, use symbol # to mean protected
Book # pages : int + pageMessage() : void Words Dictionary - definitions : int + main (args : String[]) : void + definitionMessage() : void Example from Text
Constructors • Constructors are not inherited, but can be added in the usual way: class A {… public A() { count = 1; } } class B {… public B(int n) { setCount(n); } }
The super Reference • Sometimes, we want to access something in the super class • For this, we use the super identifier • Similar to this, the meaning of super depends on the context • Using super gives access to the methods of the super class • This is particularly useful in constructors
The super Reference • A child’s constructor is responsible for calling the parent’s constructor • The first line of a child’s constructor should use the super reference to call the parent’s constructor • Why? To make sure the “parent-part” is initialized • This happens whether you like it or not… • By default, super() is called automatically
Constructors (again) class A {… public A() { count = 1; } } class B {… public B(int n) { <super(); is automatically called here> setCount(n); } }
Constructors (a more useful example) class A {… public A(int n) { count = n; } } class B {… public B() { super(1); } }
Overriding Methods • A child class can override the definition of an inherited method in favor of its own • The new method must have the same signature as the parent's method, but can have a different body • The type of the object executing the method determines which version of the method is invoked
Overriding Example class Bird { boolean flying; … void flapWings() { flying = true; } }
Overriding Example class Penguin extends Bird {… void flapWings() { return; } }
Accessing Parent Methods • Sometimes you may want to access the definition of a method from the parent class • You can use super to do this public void method(int x) { // can put extra stuff here super.method(x); }
Overloading vs. Overriding • Overloading deals with multiple methods with the same name in the same class, but with different signatures • Overriding deals with two methods, one in a parent class and one in a child class, that have the same signature • Overloading lets you define a similar operation in different ways for different parameters • Overriding lets you define a similar operation in different ways for different object types
Single Inheritance • Java supports single inheritance, meaning that a derived class can have only one parent class • Java does not support multiple inheritance • e.g. a motorhome is a vehicle and a house • We use interfaces to fake multiple inheritance
The Object Class • Single inheritance means that we can think of all classes as a single family tree • The built-in class Object is the root of this tree • A class that doesn’t explicitly extend anything has Object as its parent class • i.e. these are equivalent • class Foo{…} & class Foo extends Object{…} • Object contains some methods (toString, equals) that are used unless overridden
Built-in Classes • It’s also possible to inherit from built-in classes • Even if you don’t know the original implementation, can still add new methods • e.g. list with extra data (ArrayList with additional instance variables); Scanner than can also read in a custom type; ….
When to Inherit • Inheritance is a powerful tool in OO design • Easy reuse of code; works naturally with problems that have a hierarchy of objects • Don’t confuse inheritance with aggregation • A should extend B only if “A is-a B” or “A is a more specific version of B” or “A can be subsituted for B” • … not just because you need to use the parts of B
Example: Shapes • Suppose we want to represent a collection of shapes (in a drawing program) • square, rectangle, circle (maybe others later) • All of these have some things in common • position: the x-y coordinates of the shape • getters and setters for the position • translate(x,y): move the shape by this much • Create a class Shape that implements these
Example: Shapes • Each of these will inherit Shape • Rectangle • add instance variables height and width • Square • inherit Rectangle and ensure height==width • Circle • add radius, interpret position as the centre
Example: Shapes • The class definitions: • class Shape {…} • class Rectangle extends Shape {…} • class Square extends Rectangle {…} • class Circle extends Shape {…} • Note… this is not right: • class Rectangle extends Square {…} • A square is a certain kind of rectangle, and this should be evident in your code
Abstract Classes • Not every class can be instantiated • use reserved word abstract to indicate that a class cannot be instantiated • used for place-holders in hierarchy • make contain “abstract methods” • e.g. Shape • Abstract classes are just for code reuse, and for designing a nice class hierarchy
Using final • Methods may be marked final • public final myMethod(){…} • cannot be overridden • forces a method to have fixed behaviour • Classes may be marked final • public final class MyClass {…} • cannot be inherited • forces all methods to have fixed behaviour