Abstraction hides implementation details and exposes only necessary features. Focus on what an object does, not how it does it.
A class that cannot be instantiated. Can have both abstract methods (no body) and concrete methods (with body). Subclasses must implement all abstract methods to become concrete.
abstract class Animal {
void eat() { System.out.println("This animal eats food."); }
abstract void sound();
}
class Dog extends Animal {
@Override
void sound() { System.out.println("The dog barks."); }
}
class Cat extends Animal {
@Override
void sound() { System.out.println("The cat meows."); }
}
Animal myDog = new Dog();
myDog.eat(); // Inherited concrete method
myDog.sound(); // Dog's override
class Animal {
public:
void eat() { cout << "This animal eats food." << endl; }
virtual void sound() = 0; // Pure virtual = abstract
};
class Dog : public Animal {
public:
void sound() override { cout << "The dog barks." << endl; }
};
class Cat : public Animal {
public:
void sound() override { cout << "The cat meows." << endl; }
};
Animal* myDog = new Dog();
myDog->eat(); // Inherited concrete
myDog->sound(); // Dog's override
from abc import ABC, abstractmethod
class Animal(ABC):
def eat(self):
print("This animal eats food.")
@abstractmethod
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("The dog barks.")
class Cat(Animal):
def sound(self):
print("The cat meows.")
myDog = Dog()
myDog.eat() # Inherited concrete
myDog.sound() # Dog's override
A contract that implementing classes must fulfill. All methods are implicitly abstract (pre-Java 8). In C++, an interface is just an abstract class with all pure virtual methods. In Python, use ABC with only abstract methods.
interface Animal {
void sound();
void eat();
}
class Dog implements Animal {
@Override
public void sound() { System.out.println("The dog barks."); }
@Override
public void eat() { System.out.println("The dog eats food."); }
}
Animal myDog = new Dog();
myDog.eat();
myDog.sound();
class Animal {
public:
virtual void sound() = 0;
virtual void eat() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void sound() override { cout << "The dog barks." << endl; }
void eat() override { cout << "The dog eats food." << endl; }
};
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self): pass
@abstractmethod
def eat(self): pass
class Dog(Animal):
def sound(self):
print("The dog barks.")
def eat(self):
print("The dog eats food.")
Belong to the class, not an instance. Called on the class itself. Can only access other static members.
class Example {
static void staticMethod() {
System.out.println("This is a static method.");
}
}
Example.staticMethod(); // No object needed
class Example {
public:
static void staticMethod() {
cout << "This is a static method." << endl;
}
};
Example::staticMethod(); // No object needed
class Example:
@staticmethod
def staticMethod():
print("This is a static method.")
Example.staticMethod() // No object needed
Allow adding new methods to interfaces without breaking existing implementations. Before Java 8, adding a method to an interface broke every class that implemented it.
interface Example {
default void defaultMethod() {
System.out.println("Default implementation");
}
}
class Demo implements Example { }
Example obj = new Demo();
obj.defaultMethod(); // Inherits default
// C++ has no default methods in interfaces.
// Use a base class with a concrete method instead.
# Python has no default methods in interfaces.
# Use a base class with a concrete method instead.
Why introduced: Library evolution. Before Java 8, adding
stream() to Collection would break every implementation. With
default methods, existing code works unmodified.
Yes. An abstract class can extend another abstract class. The child abstract class can either implement the parent's abstract methods or leave them unimplemented (must remain abstract).
Yes to constructor, no to instantiation. An abstract class can have
constructors for field initialization, but you cannot use new on it directly. The
constructor is called via super() when a subclass is instantiated.
What happens if a concrete class extends an abstract class without implementing all abstract methods?
What does this print?
abstract class Calc {
int mult(int a, int b) { return a * b; }
abstract int add(int a, int b);
}
class ExactCalc extends Calc {
int add(int a, int b) { return a + b; }
}
ExactCalc c = new ExactCalc();
System.out.println(c.mult(3, 4) + " " + c.add(3, 4));
Abstraction ⇒ hide implementation details, expose only essential features
Focus ⇒ WHAT an object does, not HOW (vs Encapsulation ⇒ bundles data + methods)
Instantiable ⇒ cannot instantiate directly with new
Members ⇒ abstract methods (no body) + concrete methods (with body)
Subclass ⇒ must implement ALL abstract methods to become a concrete class
Contract ⇒ implementing classes MUST fulfill all method signatures
Methods ⇒ implicitly abstract (pre-Java 8)
Java 8+ ⇒ default methods added for backward compatibility
C++ ⇒ no interface keyword ; use pure virtual base class
Python ⇒ ABC + @abstractmethod
Static methods ⇒ belong to class ; called via
ClassName.method()
Default methods ⇒ default keyword provides body in interface without breaking
existing callers
a) Abstract class constructor ⇒ allowed for field init ; cannot instantiate directly
b) Abstract extending abstract ⇒ valid ; child remains abstract if it doesn't implement parent methods
Primary source: Oracle Java Tutorials — Abstract Methods and Classes. Ask me anything that's unclear.
Questions? Ask your agent — you can follow up on any concept, quiz answer, or how this applies to a specific coding problem. Review the Java glossary or syntax quick reference for a compressed overview.