Chapter 8 Class Design Notes1 Flashcards
Class Design
Understanding Inheritance
- Inheritance is the process by which a subclass automatically includes any public or protected members of the class, including primitives, objects, or methods, defined in the parent class.
- subclass or child class
- superclass or parent class
-
inheritance is transitive
Z class –> Y class –> X class - Package-private members are available if the child class is in the same package as the parent class.
- private members are restricted to the class they are defined in and are never available via inheritance. This doesn’t mean the parent class doesn’t have private members that can hold data or modify an object; it just means the child class has no direct reference to them.
SINGLE VS. MULTIPLE INHERITANCE
- Java supports single inheritance, by which a class may inherit from only one direct parent class. (only can extends one class)
- Java also supports multiple levels of inheritance, by which one class may extend another class, which in turn extends another class. You can have any number of levels of inheritance, allowing each descendant to gain access to its ancestor’s members.
- To truly understand single inheritance, it may helpful to contrast it with multiple inheritance, by which a class may have multiple direct parents. By design, Java doesn’t support multiple inheritance in the language because multiple inheritance can lead to complex, often difficult-to-maintain data models.
- Java does allow one exception to the single inheritance rule that you’ll see in Chapter 9—a class may implement multiple interfaces.
How to prevent a class from being extended?
- It is possible in Java to prevent a class from being extended by marking the class with the final modifier.
- If you try to define a class that inherits from a final class, then the class will fail to compile.
INHERITING OBJECT
- In Java, all classes inherit from a single class: java.lang.Object, or Object for short.
- Furthermore, Object is the only class that doesn’t have a parent class.
- You might be wondering, “None of the classes I’ve written so far extend Object, so how do all classes inherit from it?” The answer is that the compiler has been automatically inserting code into any class you write that doesn’t extend a specific class.
Creating Classes
EXTENDING A CLASS
public abstract class ElephantSeal extends Seal { // Methods and Variables defined here }
public
ordefault (package-private)
access modifierabstract
orfinal
keyword (optional)class
keyword (required)- Class name (required)
extends
parent class (optional)
APPLYING CLASS ACCESS MODIFIERS
- top-level class can only have public or package-private access.
- An inner class is a class defined inside of another class and is the opposite of a top-level class.
- In addition to public and package-private access, inner classes can also have protected and private access.
- We will discuss inner classes in Chapter 9.
- As you might recall, a Java file can have many top-level classes but at most one public top-level class.
- In fact, it may have no public class at all.
- There’s also no requirement that the single public class be the first class in the file.
- One benefit of using the package-private access is that you can define many classes within the same Java file.
ACCESSING THE THIS
REFERENCE
public class Flamingo { private String color; public void setColor(String color) { color = color; } }
Java uses the most granular scope, so when it sees color = color, it thinks you are assigning the method parameter value to itself.
- when you have a local variable with the same name as an instance variable is to use the this reference or keyword.
- The this reference refers to the current instance of the class and can be used to access any member of the class, including inherited members.
- It can be used in any
-
instance method
, -
constructor
, - and
instance initializer block
.
-
- It cannot be used when there is no implicit instance of the class, such as in a
- static method
- or static initializer block.
public void setColor(String color) { this.color = color; }
CALLING THE SUPER
REFERENCE
super
reference refers the members accessible via inheritance.- No access to current class members
- you often only use super when you have a naming conflict via inheritance. For example, you have a method or variable defined in the current class that matches a method or variable in a parent class.
Declaring Constructors
- a constructor is a special method that matches the name of the class
- and has no return type.
- It is called when a new instance of the class is created.
- Like method parameters, constructor parameters can be any valid class, array, or primitive type, including generics, but may not include var.
CREATING A CONSTRUCTOR
public class Bunny { public Bunny() { //constructor name match class name and not return type System.out.println("constructor"); } }
- A class can have multiple constructors, so long as each constructor has a unique signature. In this case, that means the constructor parameters must be distinct.
- declaring multiple constructors with different signatures is referred to as
constructor overloading
. - Constructors are used when creating a new object. This process is called instantiation because it creates a new instance of the class. A constructor is called when we write new followed by the name of the class we want to instantiate.
DEFAULT CONSTRUCTOR
- Every class in Java has a constructor whether you code one or not.
- If you don’t include any constructors in the class, Java will create one for you without any parameters.
- This Java-created constructor is called the default constructor and is added anytime a class is declared without any constructors.
- We often refer to it as the default no-argument constructor for clarity.
- The default constructor has an empty parameter list and an empty body.
private constructors
> [!NOTE]
Having only private constructors
in a class tells the compiler not to provide a default no-argument constructor.It also prevents other classes from instantiating the class.This is useful when a class has only static methods or the developer wants to have full control of all calls to create new instances of the class.Remember, static methods in the class, including a main() method, may access private members, including private constructors
.
CALLING OVERLOADED CONSTRUCTORS WITH this()
- Constructors can be called only by writing
new
before the name of the constructor. - They are not like normal methods that you can just call.
- Use
this()
to calls another constructor on the same instance of the class. - the
this()
call must be the first statement in theconstructor
. - The side effect of this is that there can be only one call to
this()
in any constructor
There’s one last rule for overloaded constructors you should be aware of.
- The compiler is capable of detecting that this constructor is calling itself infinitely. Since this code can never terminate, the compiler stops and reports this as an error.
public class Gopher { public Gopher(int dugHoles) { this(5); // DOES NOT COMPILE } }
- the constructors call each other, and the process continues infinitely. Since the compiler can detect this, it reports this as an error.
public class Gopher { public Gopher() { this(5); // DOES NOT COMPILE } public Gopher(int dugHoles) { this(); // DOES NOT COMPILE } }
THIS VS. THIS()
- Despite using the same keyword, this and this() are very different.
- The first, this, refers to an instance of the class,
- while the second, this(), refers to a constructor call within the class.
- The exam may try to trick you by using both together, so make sure you know which one to use and why.
CALLING PARENT CONSTRUCTORS WITH SUPER()
- In Java, the first statement of every constructor is either a call to another constructor within the class, using
this()
, or a call to a constructor in the direct parent class, usingsuper()
. - If a parent constructor takes arguments, then the
super()
call also takes arguments.
SUPER VS. SUPER()
- Like this and this(), super and super() are unrelated in Java.
- The first,
super
, is used to reference members of the parent class, - while the second,
super()
, calls a parent constructor.
- The first,
- Anytime you see the super keyword on the exam, make sure it is being used properly.
Understanding Compiler Enhancements
Java compiler automatically inserts a call to the no-argument constructor super() if you do not explicitly call this() or super() as the first line of a constructor.
ARE CLASSES WITH ONLY PRIVATE CONSTRUCTORS CONSIDERED FINAL?
- only an inner class defined in the class itself can extend it.
- An inner class is the only one that would have access to a private constructor and be able to call super().
- Other top-level classes cannot extend such a class.
- Don’t worry—knowing this fact is not required for the exam. We include it here for those who were curious about declaring only private constructors.
Missing a Default No-Argument Constructor
What happens if the parent class doesn’t have a no-argument constructor?
- you must create at least one constructor in your child class that explicitly calls a parent constructor via the super() command.
- We can fix this by adding a call to a parent constructor that takes a fixed argument.
public class Mammal { public Mammal(int age) {} } public class Elephant extends Mammal { // DOES NOT COMPILE }
SUPER() ALWAYS REFERS TO THE MOST DIRECT PARENT
For constructors, though, super() always refers to the most direct parent.
CONSTRUCTORS AND FINAL FIELDS
-
final static variables must be assigned a value exactly once. You saw this happen in the
- line of the declaration
- and in a static initializer.
-
Instance variables marked
final
follow similar rules. They can be assigned values in- the line in which they are declared
- or in an instance initializer.
- The constructor is part of the initialization process, so it is allowed to assign final instance variables in it.
- For the exam, you need to know one important rule. By the time the constructor completes, all final instance variables must be assigned a value.
- Unlike
local final variables
, which are not required to have a value unless they are actually used,final instance variables
must be assigned a value. - Default values are not used for these variables.
- If they are not assigned a value in the line where they are declared or in an instance initializer, then they must be assigned a value in the constructor declaration. Failure to do so will result in a compiler error on the line that declares the constructor.