Interfaces as contracts in Java
What a type can do, not how; implements.
A promise, not a recipe
An interface lists WHAT a type can do, never HOW. Think of a wall socket: any appliance with the right plug works, whatever is inside it. A method without a body, like double area();, is automatically public and abstract. And you can't write new Shape() — a contract alone can't do any work.
interface Shape {
double area();
}Signing the contract
A class signs with implements — meaning "I promise to provide all these methods". It must give every abstract method a body. Forget one, and the class either has to be declared abstract itself or it won't compile.
class Square implements Shape {
double side = 2;
public double area() {
return side * side;
}
}Same call, different body
The variable is a Pet, the object is a Fish. What prints?
interface Pet { String hi(); }
class Fish implements Pet {
public String hi() { return "Blub"; }
}
void main() {
Pet p = new Fish();
System.out.println(p.hi());
}BlubnullCompile error: Pet's hi() has no body
Show the answer
The variable's type decides which methods you may call; the actual object decides which body runs. p is declared Pet, but the object is a Fish, so Fish's body runs. Add a Dog class and the same p.hi() line could print "Woof".
The missing public
Interface methods are implicitly public. If your class implements one without writing public, it gets package-private access — weaker than public. An override can never reduce visibility, so this is a compile error, not a runtime surprise.
interface Greeter { String greet(); }
class Hi implements Greeter {
String greet() { return "hi"; } // error
}Half a promise
Engine declares start() and stop(). class Car implements Engine only writes start(). What does the compiler say?
Think about it, then reveal the answer
Compile error: Car is not abstract and does not override stop(). Either implement stop() or declare abstract class Car and let a subclass finish the job.
Plug in, don't rewrite
Checkout code that only calls PaymentMethod.pay(amount) never changes when the team adds Apple Pay: you write one new class that implements PaymentMethod, and it just plugs in. The same trick lets tests swap a real payment gateway for a fake one.
Key takeaways
- Interface methods without a body are implicitly public and abstract
- implements = 'I promise to provide all these methods'
- Miss one method and the class must be abstract, or it won't compile
- You can't write new Shape() when Shape is an interface
💡 A wall socket is a contract: any appliance with the right plug works, whatever is inside it.
Runnable has been in Java since version 1.0 in 1996 — and it is still the same tiny contract: one method, run().
Practice questions
Does this compile?
interface Greeter {
String greet();
}
class Hi implements Greeter {
String greet() { return "hi"; }
}- Yes, it compiles fine
- No: greet() in Hi must be public
- No: Hi must be declared abstract
- It compiles, but calling greet() fails at runtime
Check your answer
No: greet() in Hi must be public. Greeter.greet() is implicitly public. Hi's version has package-private access, which is weaker, and an override may never reduce visibility.
What does this print?
interface Animal { String sound(); }
class Dog implements Animal {
public String sound() { return "Woof"; }
}
class Cat implements Animal {
public String sound() { return "Meow"; }
}
void main() {
for (Animal a : List.of(new Cat(), new Dog()))
System.out.println(a.sound());
}- Meow Woof
- Woof Meow
- Animal Animal
- Compile error
Check your answer
Meow Woof. The variable type Animal decides which methods you may call; the actual object decides which body runs. The list holds a Cat then a Dog.