Invalid Abstract Method Declarations
public abstract class Turtle {
public abstract long eat() // DOES NOT COMPILE
public abstract void swim() {}; // DOES NOT COMPILE
public abstract int getAge() { // DOES NOT COMPILE
return 10;
}
public void sleep; // DOES NOT COMPILE
public void goInShell(); // DOES NOT COMPILE
}eat(), does not compile because it is marked abstract but does not end with as semicolon (;).swim() and getAge(), do not compile because they are marked abstract, but they provide an implementation block enclosed in braces ({}).sleep, does not compile because it is missing parentheses, (), for method arguments.goInShell(), does not compile because it is not marked abstract and therefore must provide a body enclosed in braces.abstract method declaration must end in a semicolon without any braces.If we changed the access modifier from private to protected in the parent class Whale, would the code compile? Let’s take a look:
public abstract class Whale {
protected abstract void sing();
}
public class HumpbackWhale extends Whale {
private void sing() { // DOES NOT COMPILE
System.out.println("Humpback whale is singing");
}
}In this modified example, the code will still not compile, but for a completely different reason. If you remember the rules for overriding a method, the subclass cannot reduce the visibility of the parent method, sing(). Because the method is declared protected in the parent class, it must be marked as protected or public in the child class. Even with abstract methods, the rules for overriding methods must be followed.
test
REVIEWING ABSTRACT CLASS RULES
Abstract Class Definition Rules
1. Abstract classes cannot be instantiated.
2. All top-level types, including abstract classes, cannot be marked protected or private.
3. Abstract classes cannot be marked final.
4. Abstract classes may include zero or more abstract and nonabstract methods.
5. An abstract class that extends another abstract class inherits all of its abstract methods.
6. The first concrete class that extends an abstract class must provide an implementation for all of the inherited abstract methods.
7. Abstract class constructors follow the same rules for initialization as regular constructors, except they can be called only as part of the initialization of a subclass.
Abstract Method Definition Rules
Abstract Method Definition Rules
1. Abstract methods can be defined only in abstract classes or interfaces.
2. Abstract methods cannot be declared private or final.
3. Abstract methods must not provide a method body/implementation in the abstract class in which they are declared.
4. Implementing an abstract method in a subclass follows the same rules for overriding a method, including covariant return types, exception declarations, etc.
DEFINING AN INTERFACE
public abstract interface CanBurrow {
public abstract Float getSpeed(int age);
public static final int MINIMUM_DEPTH = 2;public or default (package-private) access modifierabstract)interface keywordpublic abstract) - Abstract interface methodpublic static final) - Interface variableOne aspect of an interface declaration that differs from an abstract class is that it contains implicit modifiers. An implicit modifier is a modifier that the compiler automatically adds to a class, interface, method, or variable declaration.
public abstract interface WalksOnTwoLegs {}Implementing an interface
public class FieldMouse implements Climb, CanBurrow {
public Float getSpeed(int age) {
return 11f;
}
}Many of the rules for class declarations also apply to interfaces including the following :
top-level class or interface can only be declared with public or package-private access.It may help to think of an interface as a specialized abstract class, as many of the rules carry over. Just remember that an interface does not follow the same rules for single inheritance and instance initialization with constructors, as a class does.
test
WHAT ABOUT ENUMS?
public enum Color {
RED, YELOW, BLUE, GREEN, ORANGE, PURPLE
}Like classes and interfaces, enums can have more complex formations including methods, private constructors, and instance variables.
INSERTING IMPLICIT MODIFIERS
The following list includes the implicit modifiers for interfaces that you need to know for the exam:
Interfaces are assumed to be abstract.Interface variables are assumed to be public, static, and final.Interface methods without a body are assumed to be abstract and public.public interface Soar {
int MAX_HEIGHT = 10;
final static boolean UNDERWATER = true;
void fly(int speed);
abstract void takeoff();
public abstract double dive();
}
public abstract interface Soar {
public static final int MAX_HEIGHT = 10;
public final static boolean UNDERWATER = true;
public abstract void fly(int speed);
public abstract void takeoff();
public abstract double dive();
}Conflicting Modifiers
public interface Dance {
private int count = 4; // DOES NOT COMPILE
protected void step(); // DOES NOT COMPILE
}
public interface Sing {
float volume = 10;
abstract void start();
}
Cannot mark method or variable with protected or private modifier.
as the compiler will apply the public modifier to both, resulting in a conflict.
public interface Sing {
float volume = 10;
abstract void start();
}omitting the access modifier indicates default (package-private) access.
When working with interface members, though, the lack of access modifier always indicates public access. (implicit modifier)
1: private final interface Crawl {
2: String distance;
3: private int MAXIMUM_DEPTH = 100;
4: protected abstract boolean UNDERWATER = false;
5: private void dig(int depth);
6: protected abstract double depth();
7: public final void surface(); }Every single line of this example, including the interface declaration, does not compile!
final, which cannot be applied to an interface since it conflicts with the implicit abstract keyword.private, which conflicts with the public or package-private access for top-level interfaces.final, and since interface methods without a body are assumed to be abstract, the compiler throws an exception for using both abstract and final keywords on a method.Differences between Interfaces and Abstract Classes
Even though abstract classes and interfaces are both considered abstract types, only interfaces make use of implicit modifiers. This means that an abstract class and interface with similar declarations may have very different properties.
abstract class Husky {
abstract void play();
}
interface Poodle {
void play();
}class Webby extends Husky {
void play() {}
}
class Georgette implements Poodle {
void play() {}
}class Georgette implements Poodle {
public void play() {}
}INHERITING AN INTERFACE
An interface can be inherited in one of three ways.
* An interface can extend another interface.
* A class can implement an interface.
* A class can extend another class whose ancestor implements an interface.
Mixing Class and Interface Keywords
public interface CanRun {}
public class Cheetah extends CanRun {} // DOES NOT COMPILE
public class Hyena {}
public interface HasFur extends Hyena {} // DOES NOT COMPILEclass1 extends class2 interface1 extends interface2, interface3, ... class1 implements interface2, interface3, ...
Duplicate Interface Method Declarations
Since Java allows for multiple inheritance via interfaces, you might be wondering what will happen if you define a class that inherits from two interfaces that contain the same abstract method.
public interface Herbivore {
public void eatPlants();
}
public interface Omnivore {
public void eatPlants();
public void eatMeat();
}In this scenario, the signatures for the two interface methods eatPlants() are duplicates. As they have identical method declarations, they are also considered compatible. By compatibility, we mean that the compiler can resolve the differences between the two declarations without finding any conflicts. You can define a class that fulfills both interfaces simultaneously.
public class Bear implements Herbivore, Omnivore {
public void eatMeat() {
System.out.println("Eating meat");
}
public void eatPlants() {
System.out.println("Eating plants");
}
}As we said earlier, interfaces simply define a set of rules that a class implementing them must follow. If two abstract interface methods have identical behaviors—or in this case the same method declaration—you just need to be able to create a single method that overrides both inherited abstract methods at the same time.
What if the duplicate methods have different signatures?
If the method name is the same but the input parameters are different, there is no conflict because this is considered a method overload. We demonstrate this principle in the following example:
public interface Herbivore {
public int eatPlants(int quantity);
}
public interface Omnivore {
public void eatPlants();
}
public class Bear implements Herbivore, Omnivore {
public int eatPlants(int quantity) {
System.out.println("Eating plants: "+quantity);
return quantity;
}
public void eatPlants() {
System.out.println("Eating plants");
}
}In this example, we see that the class that implements both interfaces must provide implementations of both versions of eatPlants(), since they are considered separate methods.
What if the duplicate methods have the same signature but different return types?
In that case, you need to review the rules for overriding methods.
Let’s try an example:
interface Dances {
String swingArms();
}
interface EatsFish {
CharSequence swingArms();
}
public class Penguin implements Dances, EatsFish {
public String swingArms() {
return "swing!";
}
}What if the duplicate methods have the same signature but different return types?
return types are not covariant
Let’s take a look at a sample where the return types are not covariant:
interface Dances {
int countMoves();
}
interface EatsFish {
boolean countMoves();
}
public class Penguin implements Dances, EatsFish { // DOES NOT COMPILE
...
}Since it is not possible to define a version of countMoves() that returns both int and boolean, there is no implementation of the Penguin that will allow this declaration to compile. It is the equivalent of trying to define two methods in the same class with the same signature and different return types.
test
The compiler would also throw an exception if you define an abstract class or interface that inherits from two conflicting abstract types, as shown here:
interface LongEars {
int softSkin();
}
interface LongNose {
void softSkin();
}
interface Donkey extends LongEars, LongNose {} // DOES NOT COMPILE
abstract class Aardvark implements LongEars, LongNose {} // DOES NOT COMPILEAll of the types in this example are abstract, with none being concrete. Despite the fact they are all abstract, the compiler detects that Donkey and Aardvark contain incompatible methods and prevents them from compiling.
Abstract Reference Types
When working with abstract types, you may prefer to work with the abstract reference types, rather than the concrete class. This is especially common when defining method parameters. Consider the following implementation:
Interface List
import java.util.*;
public class Zoo {
public void sortAndPrintZooAnimals(List animals) {
Collections.sort(animals);
for(String a : animals) {
System.out.println(a);
}
}
}This class defines a method that sorts and prints animals in alphabetical order. At no point is this class interested in what the actual underlying object for animals is. It might be an ArrayList, which you have seen before, but it may also be a LinkedList or a Vector (neither of which you need to know for the exam).
Casting Interfaces
String lion = "Bert"; Long tiger = (Long)lion; // DOSE NOT COMPILE
With interfaces, there are limitations to what the compiler can validate. For example, does the following program compile?
1: interface Canine {}
2: class Dog implements Canine {}
3: class Wolf implements Canine {}
4:
5: public class BadCasts {
6: public static void main(String[] args) {
7: Canine canine = new Wolf();
8: Canine badDog = (Dog)canine;
9: } }8: Object badDog = (String)canine; // DOES NOT COMPILE
Since String does not implement Canine, the compiler recognizes that this cast is not possible.
In Chapter 3, “Operators,” we showed that the compiler will report an error if you attempt to use the instanceof operator with two unrelated classes, as follows:
Number tickets = 4;
if(tickets instanceof String) {} // DOES NOT COMPILEtest