Chapter 29 : Interface Continuation
Table of contents
- A Short Revision on Yesterday’s Class: Interface
- Difference Between extends and implements
- Phase 2: Combining extends and implements
- Summary of Key Differences
- Case 1: Implementing Multiple Interfaces in a Single Class
- Case 2: Extending a Class and Implementing an Interface Together
- Why Does extends Come First, and implements Follow?
- Final Example: Combining extends and implements
- Case 3: An Interface Can Extend Any Number of Interfaces
- Example:
- Why Is This Useful?
- Answer the Following Questions:
- Expression: X extends Y
- Section: Understanding the JDBC API Interface
- Overview of JDBC API
- Understanding Interface Variables in Java
- Key Properties of Interface Variables:
- Why are Interface Variables Public, Static, and Final?
- Example: Interface Variables
- Interface Variable Example
- Breakdown of the Memory Map:
- Accessing Variables from an Interface:
- Local Variables vs. Interface Variables:
A Short Revision on Yesterday’s Class: Interface
In the previous class, we discussed the concept of interfaces in Java. Interfaces are essentially a contract between a client (the user) and a service provider (the class that implements the interface). In technical terms, interfaces provide 100% abstraction, meaning they don’t contain any concrete implementation, only method declarations that need to be defined by the implementing class.
Difference Between extends
and implements
1. extends
(Inheritance)
Used when a class inherits from another class or an interface extends another interface.
Key Points:
A class can extend only one class at a time (single inheritance).
If extending a class, it inherits all the non-private fields and methods of the parent class.
Can override methods from the parent class.
The keyword
super
is used to refer to the parent class's methods or constructor.
Example:
class Parent { void display() { System.out.println("Parent class method"); } } class Child extends Parent { void display() { System.out.println("Child class overrides Parent method"); } } public class Main { public static void main(String[] args) { Child child = new Child(); child.display(); // Output: Child class overrides Parent method } }
2. implements
(Interface Implementation)
Used when a class agrees to adhere to the contract of one or more interfaces.
Key Points:
A class can implement multiple interfaces simultaneously.
The class must provide concrete implementations for all abstract methods in the interfaces.
Enables multiple inheritance of behavior.
Example:
interface A { void methodA(); } interface B { void methodB(); } class C implements A, B { public void methodA() { System.out.println("Implementing methodA from interface A"); } public void methodB() { System.out.println("Implementing methodB from interface B"); } } public class Main { public static void main(String[] args) { C obj = new C(); obj.methodA(); // Output: Implementing methodA from interface A obj.methodB(); // Output: Implementing methodB from interface B } }
Phase 2: Combining extends
and implements
A class can extend one class (inheritance) and implement multiple interfaces at the same time. This allows a class to inherit behavior and attributes from a single superclass while also conforming to the contracts defined by multiple interfaces.
Example:
class Parent { void parentMethod() { System.out.println("Parent class method"); } } interface A { void methodA(); } interface B { void methodB(); } class Child extends Parent implements A, B { public void methodA() { System.out.println("Implementing methodA from interface A"); } public void methodB() { System.out.println("Implementing methodB from interface B"); } } public class Main { public static void main(String[] args) { Child child = new Child(); child.parentMethod(); // Output: Parent class method child.methodA(); // Output: Implementing methodA from interface A child.methodB(); // Output: Implementing methodB from interface B } }
Summary of Key Differences
Feature | extends | implements |
Purpose | Inherit from a superclass or interface. | Implement interface(s). |
Inheritance | Single inheritance. | Multiple inheritance for interfaces. |
Number of Relationships | One class can extend only one class. | A class can implement multiple interfaces. |
Method Implementation | Can override superclass methods. | Must implement all abstract methods. |
This differentiation showcases how extends
and implements
enable flexibility in Java's object-oriented programming model.
Case 1: Implementing Multiple Interfaces in a Single Class
Instead of creating two separate classes for each interface, we can implement both interfaces (IOne
and ITwo
) in a single class. This allows us to manage multiple behaviors in a single place while keeping the code clean.
Example:
class CommonImpl implements IOne, ITwo {
public void m1() {
System.out.println("Method m1 from IOne");
}
public void m2() {
System.out.println("Method m2 from ITwo");
}
}
In this case, the CommonImpl
class implements both IOne
and ITwo
. It provides implementations for the m1()
method from IOne
and the m2()
method from ITwo
. This shows how a class can handle multiple interfaces, increasing flexibility and modularity in the code.
Key Takeaway: Java allows a class to implement multiple interfaces, providing different sets of functionalities, unlike extends
, where a class can only inherit from one parent class.
Case 2: Extending a Class and Implementing an Interface Together
Now, let’s see how to extend a class and implement an interface simultaneously in one class. Suppose we have a class Sample
with a method m1()
, and we also have an interface IDemo
with a method m2()
.
class Sample {
public void m1() {
System.out.println("Method m1 from Sample");
}
}
interface IDemo {
void m2();
}
We want to:
Reuse the functionality of
Sample
by extending it.Provide an implementation for the
IDemo
interface.
Here’s how we do it:
class IDemoImpl extends Sample implements IDemo {
@Override
public void m2() {
System.out.println("Method m2 from IDemo");
}
}
In this example:
Reusability (Inheritance): We extend the
Sample
class to reuse the methodm1()
. This is an example of inheritance, where the child class (IDemoImpl
) can use methods from the parent class (Sample
).Interface Implementation: We implement the
IDemo
interface to define the methodm2()
. This showcases polymorphism, where the class provides its own implementation for the methods defined in the interface.
This is a common pattern in Java where we use inheritance (extends
) to reuse code and implement interfaces (implements
) to add specific behavior.
Why Does extends
Come First, and implements
Follow?
Java always places extends
before implements
when both are used in a class. This is because:
Reusability (Inheritance): Inheritance allows us to reuse existing code written in the parent class, reducing duplication and promoting code reusability. This is why extending a class is prioritized.
Adding Behavior (Interface Implementation): After ensuring reusability, we use interfaces to add additional behavior to the class. This makes the class more flexible and customizable.
For interviews, a good explanation could be:
Reusability comes first because it allows us to avoid redundant code. We extend classes to inherit and reuse already written code.
Once we ensure reusability, we implement interfaces to add new behavior specific to the class.
This is why the extends
keyword always comes before implements
when both are used in a single class.
Final Example: Combining extends
and implements
class IDemoImpl extends Sample implements IDemo {
@Override
public void m1() {
System.out.println("Reused method m1 from Sample");
}
@Override
public void m2() {
System.out.println("Implemented method m2 from IDemo");
}
}
In this example:
IDemoImpl
reuses the methodm1()
from theSample
class.It provides its own implementation for the
m2()
method from theIDemo
interface.
This demonstrates how Java allows a class to extend another class while simultaneously implementing one or more interfaces, giving developers the flexibility to reuse existing code and add new behaviors efficiently.
Case 3: An Interface Can Extend Any Number of Interfaces
In Java, an interface can extend multiple interfaces at a time, unlike classes, which can extend only one class. This is one of the key features that provides flexibility and scalability when designing your application’s architecture.
Why Do We Extend Interfaces?
The primary reason for extending interfaces is to reuse and combine behaviors across different interfaces. Just as classes can extend other classes to inherit fields and methods, an interface can extend other interfaces to inherit method declarations.
When an interface extends multiple interfaces, it can combine the method declarations from those interfaces into a single unit. This is especially useful in large applications where multiple components need to share common behavior without repeating the code.
Example:
interface IOne {
void methodOne();
}
interface ITwo {
void methodTwo();
}
// IThree extends both IOne and ITwo, inheriting their methods.
interface IThree extends IOne, ITwo {
void methodThree();
}
In this example:
IThree
extends bothIOne
andITwo
. As a result,IThree
inherits the methodsmethodOne()
fromIOne
andmethodTwo()
fromITwo
.IThree
also defines a new method,methodThree()
, which adds new behavior to the interface.
Any class that implements IThree
will have to provide implementations for all the methods inherited from IOne
and ITwo
, as well as methodThree()
.
Why Is This Useful?
By extending multiple interfaces, we can modularize our code and design complex hierarchies without duplication. For example, imagine building a large software system with various components. Each component might need specific behavior (defined in interfaces), and we can combine those behaviors in a logical way by using interface inheritance.
Answer the Following Questions:
Which of the following is true?
a. A class can extend any number of classes at a time.
False: A class can extend only one class at a time (Java supports single inheritance for classes).b. An interface can extend only one interface at a time.
False: An interface can extend multiple interfaces at the same time, as demonstrated in the example above.c. A class can implement only one interface at a time.
False: A class can implement multiple interfaces at the same time.d. A class can extend a class and can implement an interface but not both simultaneously.
False: A class can extend a class and implement multiple interfaces simultaneously.e. An interface can implement any number of interfaces at a time.
False: Interfaces extend other interfaces; they do not implement them.Answer: f. None of the above
Consider the expression
X extends Y
. Which of the following possibilities forX
andY
is true?Both X and Y should be classes.
False: This is not a requirement, asX
andY
can be classes or interfaces.Both X and Y should be interfaces.
False: It is not mandatory for both to be interfaces.Both X and Y can be classes or can be interfaces.
True: Theextends
keyword can be used between two classes (class extends class
) or two interfaces (interface extends interface
).No restriction.
False: There is a restriction thatextends
must be used between classes or between interfaces, not between a class and an interface.
Answer: 3. Both X and Y can be classes or interfaces.
Expression: X extends Y
Valid Scenarios:
Class Extending Class:
- A class can extend another class.
Example:
- A class can extend another class.
class Parent {}
class Child extends Parent {}
Interface Extending Interface:
- An interface can extend one or more interfaces.
Example:
- An interface can extend one or more interfaces.
interface IOne {}
interface ITwo extends IOne {}
Thus, the rule is:
class extends class
: Validinterface extends interface
: Valid
In conclusion, X extends Y is valid if X and Y are both classes or both interfaces.
Section: Understanding the JDBC API Interface
The JDBC (Java Database Connectivity) API serves as an abstraction layer between Java applications and various database management systems (DBMS). It allows developers to interact with different databases using a common set of interfaces defined in the java.sql
package.
Diagram Representation
+---------------------+
| Java Code |
+---------------------+
|
V
+---------------------+
| JDBC API | (Abstraction Layer)
+---------------------+
|
-------------------------------------------
| | |
V V V
+------------+ +------------+ +------------+
| MySQL | | Oracle | | PostgreSQL |
+------------+ +------------+ +------------+
Overview of JDBC API
Abstraction Layer:
The JDBC API provides a standard interface for connecting to and interacting with databases. Regardless of the specific database you are using (e.g., MySQL, Oracle, PostgreSQL), the code you write to interact with it can remain consistent.Interfaces Defined by Sun Microsystems:
The interfaces in the JDBC API were specified by Sun Microsystems (now part of Oracle). These interfaces serve as contracts that any database driver (service provider) must implement. Core interfaces include:DriverManager: Manages a list of database drivers and establishes connections to the database.
Connection: Represents a connection to a specific database.
Statement: Used to execute SQL queries against the database.
PreparedStatement: A specialized statement used for executing precompiled SQL queries with or without parameters.
CallableStatement: Used to execute stored procedures in the database.
ResultSet: Represents the result set of a query, allowing retrieval of data.
Public and Abstract Methods:
All methods defined in the JDBC interfaces are implicitly public and abstract. This means:Public: The methods are accessible from any class that implements these interfaces, allowing wide usability of database drivers.
Abstract: The interface does not provide any method implementations; it only defines method signatures. The actual implementation of these methods is the responsibility of the database driver (service provider).
No Modifiers Other Than Public:
JDBC interface methods cannot use modifiers like static, private, protected, synchronized, native, or final because:Static: Methods in interfaces cannot be static as they are meant to be implemented in classes.
Private: Interface methods need to be publicly accessible.
Protected: Similar to private, they should be publicly accessible.
Synchronized: This modifier does not apply as interfaces define behavior rather than execution details.
Native: This modifier is used for methods implemented in platform-specific code; interface methods are purely abstract.
Final: This modifier prevents method overriding, contradicting the purpose of interfaces.
The JDBC API standardizes database access in Java, providing a consistent interface across various DBMS implementations. It abstracts the underlying complexities, allowing developers to focus on writing code rather than dealing with the specifics of each database system. By defining a clear set of interfaces, it ensures that all database drivers conform to the same contract, facilitating easier integration and portability of Java applications across different databases. This approach not only promotes code reuse but also enhances the maintainability of applications.
Understanding Interface Variables in Java
In Java, when we define variables inside an interface, they behave quite differently from class variables. Here, we'll explain how interface variables are stored in memory .
Key Properties of Interface Variables:
Public: Interface variables are automatically marked as
public
. This is done to make these variables accessible to all implementing classes.Static: They are also implicitly
static
, meaning they belong to the interface itself rather than any object instance of the implementing class.Final: All interface variables are
final
, making them constants. Once a value is assigned, it cannot be changed by the implementing classes.
Why are Interface Variables Public, Static, and Final?
Public: The reason interface variables are
public
is to ensure that any class implementing the interface has direct access to the variables. This makes them universally accessible across any implementation.Static: Since these variables are meant to be common across all implementing classes, they are
static
. Thus, they are stored in the Method Area of memory (Class Data Area), shared by all instances of implementing classes.Final: Interface variables represent constant values that cannot be modified. This is essential in situations where a common, unchangeable value is needed across different implementations. If an implementing class attempts to modify the variable, a compile-time error will occur.
Example: Interface Variables
interface IRemote {
public static final int MIN_VOLUME = 0;
public static final int MAX_VOLUME = 100;
}
class LG implements IRemote {
public void displayVolumeLimits() {
System.out.println("Min Volume: " + IRemote.MIN_VOLUME);
System.out.println("Max Volume: " + IRemote.MAX_VOLUME);
}
}
In the above example:
MIN_VOLUME
andMAX_VOLUME
are constants, and LG has access to them because they arepublic static final
.These variables are not specific to any object of class
LG
; they are properties of the interface itself.
Interface Variable Example
When the LG
class implements the IRemote
interface, the variables MIN_VOLUME
and MAX_VOLUME
are stored in the Method Area of the JVM memory, since they are static.
Let's map how this looks in the memory:
Memory Map:
+-------------------------------------------------+
| Method Area (Class Data) |
+-------------------------------------------------+
| IRemote interface |
| - static int MIN_VOLUME = 0 |
| - static int MAX_VOLUME = 100 |
+-------------------------------------------------+
^
|
+----------------+-------------------------------+
| Stack (Local Variables) |
+-------------------------------------------------+
| LG.displayVolumeLimits() |
| - no local variables for interface constants |
+-------------------------------------------------+
Breakdown of the Memory Map:
Method Area:
This is where class-level data is stored. Since the interface variables (
MIN_VOLUME
,MAX_VOLUME
) are static, they are loaded into the method area.The implementing class (
LG
) does not create a separate copy of these variables. Instead, it accesses them directly from the method area via the interface name (IRemote.MIN_VOLUME
).
Stack:
When the
displayVolumeLimits()
method is called, there are no local variables inside the method related to the interface constants.The method directly fetches the values of
MIN_VOLUME
andMAX_VOLUME
from the Method Area.
Accessing Variables from an Interface:
- In Java, static variables are accessible using the interface name (e.g.,
IRemote.MIN_VOLUME
). Since interface variables are public, static, and final, they can be accessed in this manner from anywhere in the code, provided the interface is implemented.
class Sony implements IRemote {
public void displayVolumeLimits() {
System.out.println("Min Volume (Sony): " + MIN_VOLUME); // Accessing static variable
System.out.println("Max Volume (Sony): " + MAX_VOLUME);
}
}
Local Variables vs. Interface Variables:
If a local variable in a method has the same name as the variable in the interface, the local variable takes precedence. Here's an example:
interface ISample {
int a = 10;
}
public class First implements ISample {
public static void main(String[] args) {
int a = 20; // Local variable
System.out.println(a); // Prints local variable 'a', i.e., 20
}
}
In this case:
The local variable
a = 20
inside themain()
method hides the interface variablea = 10
.The local variable in the stack memory will be accessed first unless explicitly referenced with the interface name (
ISample.a
).