JAVA 8学习笔记-第五章
Chapter 5 Class Design
1. Introduing Class Inheritance
Inheritance is the process by which the new child subclass automatically includes public or protected primitives, objects or methods defined in the parent class.
Java supports single, multiple-level inheritance, and does NOT support multiple inheritance due to its complex and difficult-to-maintain.
Java can implement multiple interfaces.
A Java file can have many classes but at most one public class.
1) Extending a Class
syntax:
public abstract class childclass extends parentclass{}
Child class is "bigger" than the parent class, it includes all the properties of parent class along with its own properties.
public and default are the only access modifiers applied to top-level classes, protected and private are inner-class modifiers.
2) Creating Java Objects
In Java, all the classes inherit from java.util.Object.
If there is no inheritance defined for a class, the Object class will be automatically inserted into the code.
3) Creating Constructors Rules
- the first statement of every constructor is to a call to another constructor within the class using this(), or a call to a constructor in a direct parent class using super()
- the super() call may not be used after the first statement of the constructor
- If there if no super() or this() call in the constructor, Java will insert an no-arguement super() call as the first statement
- If the parent doesn't have no-arguement constructor, the child requires an explicit call to a parent constructor
4) Calling Members
Parent constructors called execute first and then the child constructors.
Both this and super can be used to call a parent member, but only this can be used to call a child member.
2. Inheriting Methods
1) Override Methods
The compiler will perform following checks when you try to override an method
- The method in the child class must have the same signature as the method in the parent class.
- The method in the child class must be at least as acessible or more acessible than the method in the parent class
- The method in the child class may not throw new or boarder exception than the exception throwed in the parent class method
- The return type of the child method must be the same or a subclass of the method in the parent class
2) Reclaring Private Method
Java permits you to reclare a private method in the child class with the same or modified signature as a private method defined in the parent class.
This method in the child class is a separate and independent method, unrelated to the parent version’s method, so none of the rules for overriding methods are invoked.
3) Hiding Static Methods
Try to avoid method hiding, cause it leads to confusing and difficult-to-read code.
A hidden method occurs when you try to define a static method in the child class which has the same name sigature as a static method defined in the parent class
Five checks when you try to hide a static method:
- four rules when you override a method
- both of methods defined in child and parent class have keyword static
4) Overriding A Method vs Hiding A Method
- The child version of an overriden method is always executed for an instance regardless of whether the method call is defined in a parent or child class. In this manner, the parent method is never used unless an explicit call to the parent class is referenced, using the syntax ParentClassName.method().
- The parent version of a hidden method is always executed when the method call is defined in the parent class.
5) Creatin final Method
The final method can NOT be overriden or hidden.
3. Inheriting Variables
Java does not allow variables to be overriden but instead hidden.
1) Hiding Variables
Similar to hiding a static method, the rules for accessing parent or child variables are quite similar.
Avoid to hide variables.
4. Creating Abstract Classes
An abstract class is a class that is marked with the keyword abstract and cannot be instantiated.
An abstract method is a method defined in an abstract class, it is marked with keyword abstract and no implementation is provided in the class in which it is declared.
example:
public abstract class Animal{
public abstract String getName(); // no implementation
}
1) Defining An Abstract Class
Abstract class defination rules:
- cannot be instantiated directly
- defined with any number, including zero, of abstract or nonabstract methods
- may not mark with private or final
- an child abstract class inherits all the abstract methods of the parent class
- the first child concrete class must implement all the inherited abstract methods
Abstract method defination rules:
- may only be defined in abstract classes
- not marked with final or private
- must not provide method body in the abstract where it is declared
- implementing an abstract method in a subclass follows the same rules as overriding a method
2) Creating a Concrete Class
A concrete class is the first nonabstract subclass that extends an abstract class and is required to implement all inherited abstract methods
3) Extend An Abstract Class
Abstract class can extend other abstract classes, are not required to implement any method.
5. Implementing Interface
An interface is an abstract data type that defines a list of public abstract methods that any class implementing the interface must provide.
syntax:
public abstract interface Well{
public static final int MINIMUM_DEPTH = 2;
public abstract int getMinimumDepth(); // public and abstract are assumed
}
1) Defining an Interface
Rules for defining an interface:
- interface are assumed to have abstract modifier
- interface cannot be instantiated directly
- interface is not required to have methods
- an interface may not marked with final
- all top-level interfaces are assumed to have public or default access modifier
- all nondefault methods are assumed to have modifier abstract and public in their defination
2) Inheriting an Interface
An interface can extend another interface, but cannot implement other interface.
An interface may extend multiple interfaces.
The only connection between interface and class is that class can implement interface.
- an interface that extends another interface, as well as an abstract class that implements an interface, inherits all of the abstract methods as its own abstract methods.
- the first concrete class that implements an interface, or extends an abstract class that implements an interface must provide implementation for all the abstract methods inheritted.
3) Methods and Multiple inheritance
example 1:
public interface A{
public void eatPlants();
}
public interface B{
public void eatPlants(); // have the same behavior with method in interface A
public void eatMeat();
}
Public class Bear implements A, B{ // compile ok
public void eatPlants();
public void eatMeat();
}
example 2:
public interface A{
public int eatPlants(int quantity);
}
public interface B{
public void eatPlants(); // different behavior with method in interface A
}
Public class Bear implements A, B{ // compile ok
public int eatPlants(int quantity){ // implements methods inheritted from A and B
System.out.print("eat plants" + quantity):
return quantity;
}
public void eatPlants(){ // implements all the methods inheritted from A and B
System.out.println("eat plants"):
}
}
example 3:
public interface A{
public int eatPlants();
}
public interface B{
public void eatPlants();
}
Public class Bear implements A, B{ // class doesn't permit two methods in a class with two same name and input parameters but different return types
public int eatPlants(){ // compile error
System.out.print("eat plants: 10" ):
return quantity;
}
public void eatPlants(){ // compile error
System.out.println("eat plants"):
}
}
public abstract class Bear implements A, B{} // compile error
public interface Bear extends A,B{} // compile error
4) Interface Variables
- interface variables are assumed to be public, static and final
- the value of an variable must be set when it is declared
5) Default Interface Methods
A default method is a method defined within an interface with the keywords default in which the method body is provided.
Rules for default interface methods:
- A default method may only be declared within an interface and not within a class or an abstract class
- A default method must be marked with keyword default, and must have the method body
- A default method may not be marked to be static, final or abstract, as it may be used or overriden by a class that implements the interface
- Like all methods in the interface, a default method is assumed to be public and will not compile if marked with private or protected
When an interface extend another interface, it have three ways to deal with default methods:
- ignore it, default implementation will be used
- override it with default method
- redeclare it as an abstract method
When a class implements an interface, it have two ways to deal with default methods:
- ignore it, default implementation will be used
- override it
example:
public interface HasFins{
public default int getNumOfFins(){
return 4;
}
public default double getLongestFinLength(){
return 20.0;
}
public default boolean doFinsHaveScales(){
return true;
}
}
public interface SharkFamily extends HasFins{
public default int getNumOfFins(){ // overrides method
return 8;
}
public double getLongestFinLength(); // redeclare it as an abstract method
public boolean doFinsHaveScales(){ // compile error, overrides but not have default keyword
return false;
}
}
6) Default Methods and Multiple Inheritance
- If a class extends two interfaces that have default methods with the same name and signature, the compile will throw an exception.
- But if the subclass overrides the duplicate default methods, the code will compile.
- This holds true even for abstract classes that implements multiple interfaces.
example:
public interface Walk{
public default int getSpeed(){
return 5;
}
}
public interface Run{
public default int getSpeed(){
return 10;
}
}
public class Cats implements Walk, Run{ // compile error
public static void main(String[] args){
System.out.println(new Cats().getSpeed());
}
}
public class Cats implements Walk, Run{ // compile ok
public int getSpeed(){
return 1;
}
public static void main(String[] args){
System.out.println(new Cats().getSpeed());
}
}
7) Static Interface Methods
A static interface method defined in an interface is not inheritted in any classes that implements the interface
- marked as public
- the name of the interface is used to refer to an static interface method
- method body is optional provided
A class that implements two interfaces containing static methods with same sigature will still compile, because the static interface methods are not inheritted by the subclass and must be accessed with a reference to the interface name.
example:
public interface Hop{
static int getJumpHeight(){
return 8;
}
}
public class Bunny implements Hop{
public void printDetails(){
System.out.println(Hop.getJumpHeight()); // interface name is used to refer to an static interface method
}
}
6. Understanding Polymorphism
Java supports polymorphism. To be more precise, a Java object may be accessed using a reference with the same type as the object, a reference that is a superclass of the object, or a reference that defines an interface the object implements, either directly or through a superclass.
Once the object has been assigned to a new reference type, only the methods and variables available to that reference type are callable on the object without an explicit cast.
example:
public class Primate {
public boolean hasHair() {
return true;
} }
public interface HasTail {
public boolean isTailStriped();
}
public class Lemur extends Primate implements HasTail {
public boolean isTailStriped() {
return false;
}
public int age = 10;
public static void main(String[] args) {
Lemur lemur = new Lemur(); // a reference to object type
System.out.println(lemur.age); // 10
HasTail hasTail = lemur; // a reference to an interface that the class implements
System.out.println(hasTail.isTailStriped()); // false
Primate primate = lemur; // a reference to a class that the class extends
System.out.println(primate.hasHair()); // true
}}
1) Object vs Reference
In Java, all objects are accessed by reference, so as a developer you never have direct access to the object itself.
Changing the reference type doesn't change the object in the memory, it only change the accessibilities of the object's properties.
- the type of the object determines which properties exist within the object in memory.
- the type of the reference to the object determines which methods and variables are accessible to the Java program.
2) Casting Objects
Basic rules when casting objects:
- Casting an object from a subclass to a superclass doesn't require an explicit cast
- Casting an object from a superclass to a subclass requires an explicit cast
- The compiler will not allow casts to unrelated types
- Even when the code compiles without issue, it may throw an exception at runtime if the object being casted is not actually an instance of that class
example 1:
public class Bird{}
public class Fish{
public static void main(String[] args){
Fish fish = new Fish();
Bird bird = (Bird) fish; // unrelated class
}
}
example 2:
public class Rodent{}
public class Capy extends Rodent{
public static void main(String[] args){
Rodent rodent = new Rodent();
Capy capy = (Capy) rodent; // throws an classcastexception at runtime, since the rodent is NOT an instance of Capy
}
}
Problem can be solved by adding if (rodent isinstanceof Capy).
3) Virtual Methods
A virtual method is a method in which the specific implementation is not determined until runtime.
In fact, all non-final, non-static and non-private methods are considered as virtual methods, since any of them can be overriden at runtime.
4) Polymorphism Parameters
One of the most useful applications of polymorphism is the ability to pass instances of a subclass or interface to a method
example:
public class Rep(){
public String getName(){
return "Rep";
}
}
public class Alli extends Rep(){
public String getName(){
return "Alli";
}
}
public class Cro extends Rep(){
public String getName(){
return "Cro";
}
}
public class ZooWorker{
public static void (Rep rep){ // can pass iobject of an subclass
System.out.println("feeding" + rep.getName);
}
public static void main(String[] args){
feed(new Alli());
feed(new Cro());
feed(new Rep());
feed(null); // null can always be passed as an object value, regardless of type
}
}
If you are defining a method that will be accessible outside the current class, either to subclass of the current class or publicly to objects outside the current class, it is considered good coding practise to use superclass or interface type of input parameters whenever possible.