/*******************************************************************************
* Companion code for the book "Introduction to Software Design with Java",
* 2nd edition by Martin P. Robillard.
*
* Copyright (C) 2022 by Martin P. Robillard
*
* This code is licensed under a Creative Commons
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
*
* See http://creativecommons.org/licenses/by-nc-nd/4.0/
*
*******************************************************************************/
package e2.chapter4;
/**
* Represents an entity from which it is possible to obtain cards.
* This version supports the Null Object pattern.
*/
public CardSource {
CardSource = new CardSource() {
@Override
public boolean isEmpty() {
return true;
}
@Override
public Card draw() {
assert !isEmpty();
return ;
}
@Override
public boolean {
return true;
}
};
/**
* Returns a card from the source.
*
* @return The next available card.
* @pre !isEmpty()
*/
Card draw();
/**
* @return True if there is no card in the source.
*/
boolean isEmpty();
/**
* @return True if this instance is a null card source.
*/
boolean isNull() {
return false;
}
}
Since Java 8, it is possible to declare default methods
in interfaces. The default implementation is automatically used by all classes that declare to implement the interface. To change
default behavior, it is necessary to declare a method with the same name and list of parameters (as done in the declaration of NULL
).
In our case, this use of the default method means that all CardSource
implementations are not null by default, which eliminates some
clutter in implementing classes.
Since Java 8, it is possible to declare default methods
in interfaces. The default implementation is automatically used by all classes that declare to implement the interface. To change
default behavior, it is necessary to declare a method with the same name and list of parameters (as done in the declaration of NULL
).
In our case, this use of the default method means that all CardSource
implementations are not null by default, which eliminates some
clutter in implementing classes.
Although this method technically returns null, this value should never actually be propagated because the precondition for the method is always false.
Although this method technically returns null, this value should never actually be propagated because the precondition for the method is always false.
Fields declared in Java interfaces are (public, static, and final). This constant
provides an null object implementation of the interface. Client code can use it to represent
the absence of a CardSource
without having to implement a special case for null
values. The
null object is declared and created via an .
Fields declared in Java interfaces are (public, static, and final). This constant
provides an null object implementation of the interface. Client code can use it to represent
the absence of a CardSource
without having to implement a special case for null
values. The
null object is declared and created via an .
This method overrides the default method of the same name declared in the
interface. We will cover overriding in more detail in Chapter 7. For now, it is
enough to know that this version of isNull
will be used when the method is called
on NULL
.
This method overrides the default method of the same name declared in the
interface. We will cover overriding in more detail in Chapter 7. For now, it is
enough to know that this version of isNull
will be used when the method is called
on NULL
.
This is similar to methods in Java interfaces, which are implicitly public.
This is similar to methods in Java interfaces, which are implicitly public.
Remember the annotations for Chapter 3 about why interfaces are an important aspect of programming, by allowing polymorphism.
Remember the annotations for Chapter 3 about why interfaces are an important aspect of programming, by allowing polymorphism.
An anonymous class declaration declares and intantiates a subtype of a class or an interface
simultaneously. Because the subtype doesn't have a name (we only know that it's a subtype of
which class or interface, here CardSource
), it's anonymous.
An anonymous class declaration declares and intantiates a subtype of a class or an interface
simultaneously. Because the subtype doesn't have a name (we only know that it's a subtype of
which class or interface, here CardSource
), it's anonymous.