Search Logic Blocks

Friday, May 7, 2021

Java: Private Methods in an Interface

We have already learnt about the different kinds of methods in an Interface - We can have one more type of method in an interface - private method. Private methods in an interface work the same way as the private methods in a class. Private methods can't be accessed from outside of the Interface. Private methods are only accessed by the methods defined in the interface itself (default or static methods). The overridden methods in the implementing class also can not access the private methods.

Interface Private (Private.java)
public interface IPrivate {
public void msg();

default public void callMessage() {
message();
}

private void message() {
System.out.println("In private Method");
}
}
Class Test (Test.java)
public class Test implements IPrivate{
public void msg() {
//message();
System.out.println("In implementing class method");
}

static public void main(String args[]) {
Test test = new Test();
test.callMessage();
}
}
Conclusion - Here is the summary of different kinds of the methods in an interface -
  • Abstract methods (methods with an empty body) - Abstract methods are mandatory to be written / overridden by the implementing class. The implementing class should give structure to each abstract method in the interface.
  • Default methods (with the default code / instructions) - Default methods are not mandatory to be overridden by the implementing class, but if they are not overridden - the default method from the interface will be called.
  • Static methods (with the code) - Static methods are called directly by the interface itself, not by interface variable. So, static methods can't be overridden. If the implementing class has a method with the same name as the static method in the interface, there won't be any relation between two methods (static method in the interface and the same name method in the implementing class)
  • Private methods (with the code) - Private methods can only be accessed by default or static methods in the interface, not outside from the interface.
Code can be found at Github Link.

Thursday, May 6, 2021

Java: How to access interface methods using Interface References

In the earlier post Inheritance, we have already seen how all the child classes (Circle, Triangle and Rectangle) access the overridden methods, using the reference of the parent class (Shape). The compiler doesn't detect any difference, so there wouldn't be any compile time issues. When running the program, the JVM detects dynamically which class is referred to and accordingly the respective methods are called. This feature is called Polymorphism.


Same way, interface variables can refer its implementing classes. I have already shown this in the post Interfaces. The implementing classes (Triangle and Rectangle) are accessing the implemented methods, using the reference of the parent class (IPolygon).

Sunday, April 25, 2021

Java: Variables in an Interface

When I introduced interfaces in the post Java: Interfaces - I mentioned that, variables can be declared in an interface - "Variables can be declared inside the interface, but they must be initialized and they are implicitly final and static. The variables defined in the interface can not be changed (final) and can be accessed by interface (static) itself. All the members of the interface are implicitly public."

Let's write a simple program to test this concept - There is an interface IUserName, having a prototype to get the user name and display same to the console. There is a static method in the interface, which checks if the entered user name is valid, if yes, displays the user name else it displays the message accordingly. Interface has String class type variables which are used to store the messages. The class User implements the interface IUserName.

Interface IUserName (IUserName.java)
public interface IUserName {
// String MSG;
String MSGLEN = "User name should have atleast 8 characters!!";
String MSGNUM = "User name should have atleast one numeric character!!";
String MSGDOLLAR = "User name should not have dollar sign!!";

public void getUsername();

public void displayUsername();

public static boolean isValid(String name) {
boolean isValid = true;
// MSGLEN = "User should have ateast 10 characters!!";
if(name.length() < 8) {
System.out.println(MSGLEN);
isValid = false;
return isValid;
}
if(!name.matches(".*\\d.*")) {
System.out.println(MSGNUM);
isValid = false;
return isValid;
}
if(name.matches(".*[$].*")) {
System.out.println(MSGDOLLAR);
isValid = false;
return isValid;
}
return isValid;
}
}
Class User (User.java)
import java.util.Scanner;

public class User implements IUserName {
String userName = "";
public void getUsername() {
System.out.println("Enter the user name");
Scanner sc = new Scanner(System.in);
userName = sc.next();
if(IUserName.isValid(userName)) displayUsername();
}

public void displayUsername() {
System.out.println("User name is " + userName);
}

public static void main(String args[]) {
User user = new User();
user.getUsername();
// System.out.println(IUserName.MSGDOLLAR);
// System.out.println(user.MSGDOLLAR);
}
}
There are the following requirements for the user name to be valid -
  • must be more than 8 characters.
  • should have at least one numeric character.
  • dollar sign is not allowed.
String MSGLEN = "User name should have atleast 8 characters!!";
String MSGNUM = "User name should have atleast one numeric character!!";
String MSGDOLLAR = "User name should not have dollar sign!!";
The getUsername() method in the class User accepts a user name from the console. 
public void getUsername() {
System.out.println("Enter the user name");
Scanner sc = new Scanner(System.in);
userName = sc.next();
if(IUserName.isValid(userName)) displayUsername();
}
The method getUsername() calls the static method isValid() from the interface directly to check the validity of the entered user name. (The code uses a String class method matches, which takes a regular expression as a parameter and finds out whether the String matches with the regular expression. I will write a separate post to discuss regular expressions in detail.)
  • Checks whether the user name has at least 8 characters. If not, the message - User name should have atleast 8 characters!! - is printed on the console.
if(name.length() < 8) {
System.out.println(MSGLEN);
isValid = false;
return isValid;
}
  • Checks whether the user name has at least one numeric character. If not, the message - User name should have atleast one numeric character!! - is printed on the console. (".*\\d.*" - \\d means any digit and .* means any character with 0 or more occurrences.)
if(!name.matches(".*\\d.*")) {
System.out.println(MSGNUM);
isValid = false;
return isValid;
}
  • Checks whether the user name contains character $. If yes, the message - User name should not have dollar sign!! - is printed on the console. (".*[$].*" - [$] means single character and .* means any character with 0 or more occurrences.)
if(name.matches(".*[$].*")) {
System.out.println(MSGDOLLAR);
isValid = false;
return isValid;
}
If the user name is valid, the displayUsername() method displays the user name.
public void displayUsername() {
System.out.println("User name is " + userName);
}
Here is the output:

Enter the user name
Michael
User name should have atleast 8 characters!!

Enter the user name
MichaelJohn
User name should have atleast one numeric character!!

Enter the user name
Michael$4John
User name should not have dollar sign!!

Enter the user name
Michael8John
User name is Michael8John

Let's talk about the String variables used in the interface, we have the following observations -

If we try to declare the interface variable MSG without the initialization, 
String MSG;
it gives compile time error -

Error:(4, 15) java: = expected

Conclusion - The interface variables must be initialized.

If we  try to assign the new value to the interface variable MSGLEN,
MSGLEN = "User should have ateast 10 characters!!";
it gives compile time error -

Error:(15, 9) java: cannot assign a value to final variable MSGLEN

Conclusion - The interface variables are implicitly final. They can't be changed.

If we try to access the interface variables directly using the interface name, or through the instance of the class implementing the interface,
System.out.println(IUserName.MSGDOLLAR);
System.out.println(user.MSGDOLLAR);
there will be no compile time error -

Conclusion - The interface variables are implicitly static. They can be accessed through the interface directly as well as by the instance of the class implementing the interface.

NOTE: So, above code verifies that the variables declared in th interface are implicitly final and static.

The code can be accessed at Github Link.

Thursday, April 22, 2021

Java: Static Methods in an Interface

In our last post - Default Methods in an Interface, we saw that how we can add a default method to an existing interface and how we can override the default method in the classes, which are implementing the interface. Like a regular class, we can also have a static method in an interface and can be accessed the same way. There is no need to implement or extend the interface to access the static method.

Let's create an interface which represents an array of integer numbers. Array can be series of any kind of numbers - Prime numbers, Fibonacci numbers, Even numbers, Odd numbers or any other pattern. The interface provides a default method to create a list of integers, methods to implement the interface and a static method to display the group data in a standard way.


Interface Group - (Group.java)
public interface Group {
public int getNextNo();

public int[] getList();

public String getName();

default public int[] createGroup(int n) {
int num[] = new int[n];
for(int i = 0; i < n; i++) {
num[i] = getNextNo();
}
return num;
}

static public void displayGroup(Group g) {
int num[] = g.getList();
System.out.println(g.getName());
int n = num.length;
for(int i = 0; i < n; i++) {
System.out.print(num[i] + " ");
}
System.out.println(" ");
}
}
Methods defined in the interface -
public int getNextNo();
getNextNo() method is used to generate the new number for the particular group. This method will be implemented different for every group of numbers - prime numbers, Fibonacci numbers, etc.
public int[] getList();
getList() method returns the array of integers numbers generated in the particular group - prime, fibonacci, etc.
public String getName();
getName() method returns the name of the particular list.
default public int[] createGroup(int n) {
int num[] = new int[n];
for(int i = 0; i < n; i++) {
num[i] = getNextNo();
}
return num;
}
createGroup() method is the default method to create the list of numbers. The implementing class does not need to implement the createGroup() method, but can override the method as needed.
static public void displayGroup(Group g) {
int num[] = g.getList();
System.out.println(g.getName());
int n = num.length;
for(int i = 0; i < n; i++) {
System.out.print(num[i] + " ");
}
System.out.println(" ");
}
displayGroup() method displays the list in a particular way. This method is static method, so can be accessed directly. This method can not be overridden. In the implementing class, if there is any method with the same name, it will be totally different method and there will be no relation to static method in the interface.

Class Prime (Prime.java) for prime numbers - getNextNo() method returns the next prime number in the list
public class Prime implements Group {
int lastPrime = 1;
int groupSize = 0;
int primeList[];

Prime(int n) {
groupSize = n;
primeList = createGroup(n);
}

public int getNextNo() {
if(lastPrime >= 3) {
boolean foundNext = false;
int temp = lastPrime;
while(!foundNext) {
temp = temp + 2;
if(isPrime(temp)) {
lastPrime = temp;
foundNext = true;
}
}
} else if (lastPrime == 1) lastPrime = 2;
else if (lastPrime == 2) lastPrime = 3;
return lastPrime;
}

public int[] getList() {
return primeList;
}

public String getName() {
return "Prime Numbers List: ";
}

public boolean isPrime(int n) {
boolean prime = true;
for(int j = 3; j < n; j = j + 2) {
if((n % j) == 0) {
prime = false;
break;
}
}
return prime;
}
}
Class Fibo (Fibo.java) for Fibonacci numbers - getNextNo() returns the next Fibonacci number in the list
public class Fibo implements Group {
int lastFibo1 = 0;
int lastFibo2 = 0;
int groupSize = 0;
int FiboList[];

Fibo(int n) {
groupSize = n;
FiboList = createGroup(n);
}

public int getNextNo() {
if(lastFibo1 >= 1 && lastFibo2 >= 1) {
int temp = lastFibo2;
lastFibo2 = lastFibo2 + lastFibo1;
lastFibo1 = temp;
} else if (lastFibo2 == 0) lastFibo2 = 1;
else if (lastFibo2 == 1) {
lastFibo1 = 1;
}
return lastFibo2;
}

public int[] getList() {
return FiboList;
}

public String getName() {
return "Fibonacci Numbers List: ";
}
}
Class GroupDemo (GroupDemo.java) - Demos how to access the interface Group, to access its default and static methods, and its implementing classes (Prime, Fibo, Even and Odd) -
(NOTE: Above, I have not included code for classes Even and Odd. But these classes can be accessed at Github.)
public class GroupDemo {
public static void main(String args[]) {
Group g1 = new Prime(10);
Group.displayGroup(g1);
Group g2 = new Fibo(10);
Group g3 = new Odd(10);
Group.displayGroup(g2);
Group.displayGroup(g3);
Group g4 = new Even(10);
Group.displayGroup(g4);
}
}
Output

Prime Numbers List: 
2 3 5 7 11 13 17 19 23 29  
Fibonacci Numbers List: 
1 1 2 3 5 8 13 21 34 55  
Odd Numbers List: 
3 5 7 9 11 13 15 17 19 21  
Even Numbers List: 
2 4 6 8 10 12 14 16 18 20  

All the code can be accessed at Github Link.

Sunday, April 18, 2021

Java: Default Methods in an Interface

As we know that an interface is like a prototype, which has the methods with empty bodies and the interfaces can't be instantiated (means instance or object can't be created) like the classes. Interfaces can only be implemented by the classes or extended into another interface (we will know about inherited interfaces later). That means, once the interface is used by other classes or interfaces, it is not possible to make changes in the existing interface.

To give the flexibility to change an existing interface, without affecting it's implementing classes or inheriting interfaces, a new feature was added at the time of release of JDK8 - The default methods.

Default Methods in an Interface -
Default methods are the methods with default code statements (not the empty body), which can be added to an existing interface without any effect on the classes and interfaces using the existing interface. The new added default method has its own body, so the classes don't need to provide their implementation and they will work same as earlier before adding the default method.

Let's take the same example used in the post Introduction to Interfaces - IPolygon is an Interface, Triangle and Rectangle are the classes implementing the same interface IPolygon, and PolygonTest is a demo class showing how to use the methods of both the classes.


If we add an empty body method to the existing interface IPolygon, we need to change both the classes to implement the new method. But, if we add a new default method to the interface - there will be no effect to the classes - Triangle and Rectangle. Objects of both the classes can call the default method without  any  implementation of the method in the classes.


Default methods are created by using the keyword default. And method definition is same as like a regular method. Let's have a default method printShapeDetails(), which prints all the details of the specific shape. The code for the new default method will look like this -
default public void printShapeDetails() {
System.out.println("Shape is " + whatShape());
System.out.println("Total Sides are " + noOfSides());
System.out.println("Sides are: ");
double sides[] = getSides();
for(int i = 0; i < getSides().length; i++) {
System.out.print("Side " + (i+1) + ": " + sides[i] + "; ");
}
System.out.println();
System.out.println("Area is " + area());
System.out.println("Perimeter is " + perimeter());
System.out.println();
}
And without changing anything in both the classes - Triangle and Rectangle, the instances of these classes can call the default method, like we call other methods in the demo class PolygonTest.

Interface IPolygon
// Interface Polygon gives structure of the methods needed to work with any polygon
// Every class implementing this interface should have all the methods
public interface IPolygon {
// Returns the text telling what shape it is
public String whatShape();

// Returns the numbers of sides
public int noOfSides();

// Returns the array of lengths of all sides
public double[] getSides();

// Returns the area of the shape
public double area();

// Returns the perimeter of the shape
public double perimeter();

default public void printShapeDetails() {
System.out.println("Shape is " + whatShape());
System.out.println("Total Sides are " + noOfSides());
System.out.println("Sides are: ");
double sides[] = getSides();
for(int i = 0; i < getSides().length; i++) {
System.out.print("Side " + (i+1) + ": " + sides[i] + "; ");
}
System.out.println();
System.out.println("Area is " + area());
System.out.println("Perimeter is " + perimeter());
System.out.println();
}
}
Class Triangle
// Class Triangle implementing the interface IPolygon
public class Triangle implements IPolygon {
final int noOfSides = 3;
double side1;
double side2;
double side3;
double perimeter;
double area;

// Triangle Constructor with no arguments
Triangle() {
this.side1 = 4;
this.side2 = 4;
this.side3 = 4;
}

// Triangle Constructor with three arguments
Triangle(double side1, double side2, double side3) {
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}

// Returns the text telling what shape it is
public String whatShape() {
return "Triangle";
}

// Returns the numbers of sides
public int noOfSides() {
return noOfSides;
}

// Returns the array of lengths of all sides
public double[] getSides() {
double arrSides[] = new double[3];
arrSides[0] = side1;
arrSides[1] = side2;
arrSides[2] = side3;
return arrSides;
}

// Returns the area of the triangle
public double area() {
double p, diff1, diff2, diff3, pr;
p = perimeter / 2;
diff1 = p - side1;
diff2 = p - side2;
diff3 = p - side3;
pr = p * diff1 * diff2 * diff3;
area = Math.round(Math.sqrt(pr) * 100) / 100.0;
return area;
}

// Returns the perimeter of the triangle
public double perimeter() {
perimeter = Math.round((side1 + side2 + side3) * 100) / 100.0;
return perimeter;
}
}
Class Rectangle
// Class Rectangle implementing the interface IPolygon
public class Rectangle implements IPolygon {
final int noOfSides = 4;
double side1;
double side2;
double perimeter;
double area;

// Rectangle Constructor with no arguments
Rectangle() {
this.side1 = 4;
this.side2 = 4;
}

// Rectangle Constructor with three arguments
Rectangle(double side1, double side2) {
this.side1 = side1;
this.side2 = side2;
}

// Returns the text telling what shape it is
public String whatShape() {
return "Rectangle";
}

// Returns the numbers of sides
public int noOfSides() {
return noOfSides;
}

// Returns the array of lengths of all sides
public double[] getSides() {
double arrSides[] = new double[4];
arrSides[0] = side1;
arrSides[1] = side2;
arrSides[2] = side1;
arrSides[3] = side2;
return arrSides;
}

// Returns the area of the rectangle
public double area() {
double pr;
pr = side1 * side2;
area = Math.round(pr * 100) / 100.0;
return area;
}

// Returns the perimeter of the rectangle
public double perimeter() {
perimeter = Math.round((2 * (side1 + side2)) * 100) / 100.0;
return perimeter;
}
}
Class PolygonTest
// Class for testing the interface IPolygon and its implementing classes
public class PolygonTest {
public static void main(String args[]) {
IPolygon P[] = new IPolygon[2];
P[0] = new Triangle(16.6, 11.2, 17.9);
P[1] = new Rectangle(12.5, 15.5);

for(int i = 0; i < P.length; i++) {
System.out.println("Polygon " + (i+1) + " is " + P[i].whatShape());
System.out.println("No of sides: " + P[i].noOfSides());
double allSides[] = P[i].getSides();
System.out.print("All sides are : ");
for(int j = 0; j < allSides.length; j++) {
System.out.print("Side" + (j+1) + ": " + allSides[j] + " ");
}
System.out.println();
System.out.println("Perimeter is : " + P[i].perimeter());
System.out.println("Area is : " + P[i].area());
System.out.println();
}

for(int i = 0; i < P.length; i++) {
P[i].printShapeDetails();
}
}
}
And the output is here :-

Polygon 1 is Triangle
No of sides: 3
All sides are : Side1: 16.6   Side2: 11.2   Side3: 17.9   
Perimeter is : 45.7
Area is : 90.75

Polygon 2 is Rectangle
No of sides: 4
All sides are : Side1: 12.5   Side2: 15.5   Side3: 12.5   Side4: 15.5   
Perimeter is : 56.0
Area is : 193.75

Shape is Triangle
Total Sides are 3
Sides are: 
Side 1: 16.6; Side 2: 11.2; Side 3: 17.9; 
Area is 90.75
Perimeter is 45.7

Shape is Rectangle
Total Sides are 4
Sides are: 
Side 1: 12.5; Side 2: 15.5; Side 3: 12.5; Side 4: 15.5; 
Area is 193.75
Perimeter is 56.0

Now, we can create a new class by implementing the interface updated with new default method and override the default method in the new class. Let's add a new class called Square and write a separate method printShapeDetails() in the class Square to show the details of the square -

Class Square
// Class Square implementing the interface IPolygon
public class Square implements IPolygon {
final int noOfSides = 4;
double side;
double perimeter;
double area;

// Square Constructor with no arguments
Square() {
this.side = 4;
}

// Square Constructor with one argument
Square(double side) {
this.side = side;
}

// Returns the text telling what shape it is
public String whatShape() {
return "Square";
}

// Returns the numbers of sides
public int noOfSides() {
return noOfSides;
}

// Returns the array of lengths of all sides
public double[] getSides() {
double arrSides[] = new double[4];
arrSides[0] = side;
arrSides[1] = side;
arrSides[2] = side;
arrSides[3] = side;
return arrSides;
}

// Returns the area of the square
public double area() {
double pr;
pr = side * side;
area = Math.round(pr * 100) / 100.0;
return area;
}

// Returns the perimeter of the square
public double perimeter() {
perimeter = Math.round((4 * side) * 100) / 100.0;
return perimeter;
}

public void printShapeDetails() {
System.out.println("Shape is " + whatShape());
System.out.println("Total Sides are " + noOfSides());
System.out.println("Sides of the square are: " + this.side);
System.out.println("Area is " + area());
System.out.println("Perimeter is " + perimeter());
System.out.println();
}
}
Changes in Class PolygonTest
// Class for testing the interface IPolygon and its implementing classes
public class PolygonTest {
public static void main(String args[]) {
IPolygon P[] = new IPolygon[3];
P[0] = new Triangle(16.6, 11.2, 17.9);
P[1] = new Rectangle(12.5, 15.5);
P[2] = new Square(4);

for(int i = 0; i < P.length; i++) {
System.out.println("Polygon " + (i+1) + " is " + P[i].whatShape());
System.out.println("No of sides: " + P[i].noOfSides());
double allSides[] = P[i].getSides();
System.out.print("All sides are : ");
for(int j = 0; j < allSides.length; j++) {
System.out.print("Side" + (j+1) + ": " + allSides[j] + " ");
}
System.out.println();
System.out.println("Perimeter is : " + P[i].perimeter());
System.out.println("Area is : " + P[i].area());
System.out.println();
}

for(int i = 0; i < P.length; i++) {
P[i].printShapeDetails();
}
}
}
And the output is here -

Polygon 1 is Triangle
No of sides: 3
All sides are : Side1: 16.6   Side2: 11.2   Side3: 17.9   
Perimeter is : 45.7
Area is : 90.75

Polygon 2 is Rectangle
No of sides: 4
All sides are : Side1: 12.5   Side2: 15.5   Side3: 12.5   Side4: 15.5   
Perimeter is : 56.0
Area is : 193.75

Polygon 3 is Square
No of sides: 4
All sides are : Side1: 4.0   Side2: 4.0   Side3: 4.0   Side4: 4.0   
Perimeter is : 16.0
Area is : 16.0

Shape is Triangle
Total Sides are 3
Sides are: 
Side 1: 16.6; Side 2: 11.2; Side 3: 17.9; 
Area is 90.75
Perimeter is 45.7

Shape is Rectangle
Total Sides are 4
Sides are: 
Side 1: 12.5; Side 2: 15.5; Side 3: 12.5; Side 4: 15.5; 
Area is 193.75
Perimeter is 56.0

Shape is Square
Total Sides are 4
Sides of the square are: 4.0
Area is 16.0
Perimeter is 16.0

All the code can be found at Github Link.

Monday, March 29, 2021

Java: Nested Interface in an Interface

We had talked about interfaces and their fully / partial implementations. We also talked about Nested Interface in a Class (declaring an interface in a class) and Nested Class in an Interface (declaring a class in am interface). Let's declare an interface inside an interface (Nested Interface in an Interface) -

The inner interface class instance can be used three ways -
  • instance methods can be called directly
  • instance is passed to interface variable by reference and then methods are called through that variable
  • instance is passed to the outer interface method which takes a parameter interface variable

All three examples are shown in the code given below -
// Outer Interface
public interface OuterInterface {
public void display();
public void showInner(InnerInterface i);

// Inner Interface
public interface InnerInterface {
public void display();
}
}
// Implementation of Outer Interface
public class OuterInterfaceClass implements OuterInterface {
public void display() {
System.out.println("Display method from OuterInterfaceClass");
}

public void showInner(InnerInterface i) {
System.out.println("Show method from OuterInterfaceClass");
i.display();
}
}
// Implementation of Inner Interface
public class InnerInterfaceClass implements OuterInterface.InnerInterface {
public void display() {
System.out.println("Display method from InnerInterfaceClass");
}
}
// Demo class showing accessing inner interface in all three ways
public class Test {
public static void main (String args[]) {
// Creates a an object of class implementing OuterInterface
OuterInterfaceClass oic = new OuterInterfaceClass();
oic.display();
System.
out.println("___________________________________________________");

// Creates a an object of class implementing InnerInterface
InnerInterfaceClass iic = new InnerInterfaceClass();
iic.display();
System.
out.println("___________________________________________________");

// Creates a a variable of inner interface and assign the class variable By Reference
OuterInterface.InnerInterface oiii;
oiii = iic;
oiii.display();
System.
out.println("___________________________________________________");
// Calls the outer interface method which accesses inner interface
oic.showInner(iic);
}
}
Let's explore all three options -

InnerInterfaceClass is created by implementing inner interface InnerInterface directly.
// Implementation of Inner Interface
public class InnerInterfaceClass implements OuterInterface.InnerInterface {
public void display() {
System.out.println("Display method from InnerInterfaceClass");
}
}
1. instance methods can be called directly -

Create an instance of class implementing inner interface and then call interface methods:
// Creates a an object of class implementing InnerInterface
InnerInterfaceClass iic = new InnerInterfaceClass();
iic.display();
2. instance is passed to an interface variable by reference and then methods are called through that variable -

Declare a variable of inner interface and assign the inner class variable (Using class reference), call the method through interface variable:
// Creates a a variable of inner interface and assign the class variable By Reference
OuterInterface.InnerInterface oiii;
oiii = iic;
oiii.display();
3. instance is passed to the outer interface method which takes a parameter interface variable -

Creates an instance of class implementing outer interface and then call interface methods passing inner interface as a parameter:
// Creates a an object of class implementing OuterInterface
OuterInterfaceClass oic = new OuterInterfaceClass();
// Calls the outer interface method which accesses inner interface
oic.showInner(iic);
Here is the output of the above code -

Display method from OuterInterfaceClass
___________________________________________________
Display method from InnerInterfaceClass
___________________________________________________
Display method from InnerInterfaceClass
___________________________________________________
Show method from OuterInterfaceClass
Display method from InnerInterfaceClass

Code can be accessed on Github Link.

Tuesday, March 23, 2021

Java: Nested Class in an Interface

We already discussed about interfaces, partial interface and nested interface in a class. In this post, we will learn, how we can declare a class inside an interface. The outer interface can access the inner class in its own methods. Suppose there is an interface named as Magazine, and it has inner class named as Article. A class MagazineDemo implements the interface Magazine and creates an instance of inner class Article -

// Interface Magazine - prototype of a magazine
public interface Magazine {

// Prints the article
void postArticle(Article a);

// Gets the number of characters in an Article
int getArticleLen(Article a);

// Gets the number of words in an Article
int getArticleWords(Article a);

// Class Article in the interface Magazine
class Article {
String title;
String author;
String content;

// Article class constructor
Article(String title, String author, String content) {
this.title = title;
this.author = author;
this.content = content;
}
}
}
The interface Magazine is implemented by a demo class MagazineDemo. The main() method creates an instance of inner class Article and calls the implemented methods to print the Article details -
import java.util.Scanner;

// Implements the interface Magazine
public class MagazineDemo implements Magazine {
// Prints the Article
public void postArticle(Article a) {
System.out.println("title: " + a.title);
System.out.println("author: " + a.author);
System.out.println("content: " + a.content);
}

// Implements the interface method - getArticleLen(Article a)
public int getArticleLen(Article a) {
int len = a.content.length();
System.out.println("Article has " + len + " characters.");
return len;
}

// Implements the interface method - getArticleWords(Article a)
public int getArticleWords(Article a) {
String words[] = a.content.split(" ");
int wordCount = words.length;
System.out.println("Article has " + wordCount + " words.");
return wordCount;
}

public static void main(String args[]) {
System.out.print("Enter title:");
Scanner sc = new Scanner(System.in);
String title, author, content;
title = sc.nextLine();

System.out.print("Enter author name:");
author = sc.nextLine();

System.out.print("Enter content:");
content = sc.nextLine();
System.out.println("----------------");

MagazineDemo d = new MagazineDemo();
Article a = new Article(title, author, content);
d.getArticleLen(a);
d.getArticleWords(a);
d.postArticle(a);
}
}
Here is the example of output -

Enter title:Implementing Interfaces
Enter author name:Herbert Schildt
Enter content:Once an interface has been defined, one or more classes can implement that interface.
----------------
Article has 85 characters.
Article has 14 words.
title: Implementing Interfaces
author: Herbert Schildt
content: Once an interface has been defined, one or more classes can implement that interface.

The code can be found at Github Link.