1. Basic concepts of interfaces

In Java, a “class” decorated with the keyword interface is an interface.

Interfaces are defined as follows:

Interface Interface name {global constant; Abstract method; }Copy the code
2. Interface usage

Interfaces are used in two steps:

  1. Create the interface
  2. Implementing an interface
2.1 Creating an Interface
Public interface Move {void Move (); }Copy the code
2.2 Interface Implementation
Public implements Move {@override public void implements Movemove() {
		System.out.println("Animal move");
	}
	
}

public class Human implements Move{

	@Override
	public void move() {
		System.out.println("Human move");
	}

}

public class Car implements Move {

	@Override
	public void move() {
		System.out.println("Car move");
	}

}

public class MoveTest {

	public static void main(String[] args) {
		Move [] move = {new Animal(), new Human(), new Car()};
		for(Move m : move) { m.move(); Animal move Human move Car moveCopy the code
3. The meaning of the interface

Interfaces exist for two main reasons:

  1. It is forbidden to instantiate objects directly
  2. Breaking the limitations of single inheritance (implementing pseudo-multiple Inheritance)
3.1 Forbid instantiating objects directly

At this point, Java is even more restrictive on interfaces than on abstract classes, because interfaces don’t even have constructors, so it’s impossible to instantiate objects.

Public interface Move {// Interfaces cannot have constructors publicMove(){}
	
	void move();
	
}
Copy the code
3.2 Breaking the limitation of Single Inheritance (Pseudo-Multiple Inheritance)

Because Java allows many implementations, a class that implements multiple interfaces can be transformed into multiple interfaces, breaking the single inheritance limitation.

// source code public interface Fly {void Fly (); } public interface Fight { void fight(); } public class SuperMan implements Fly,Fight{ @Override public voidfight() {
		System.out.println("SuperMan fight");
	}

	@Override
	public void fly() {
		System.out.println("SuperMan fly"); } } public class MultiImplementsTest { public static void main(String[] args) { SuperMan sm = new SuperMan(); fly(sm); fight(sm); } private static void fly(Fly f){ f.fly(); } private static void fight(Fight f){ f.fight(); }} // SuperMan fly SuperMan fightCopy the code

As SuperMan implements Fly and Fight interfaces, SuperMan can be transformed into Fly interface or Fight interface, namely, “Multiple inheritance? .

4. Confusing concepts in interfaces
4.1 Is there a constructor for an interface?

There are no constructors in the interface. For details, please refer to 3.1 Forbidding Directly Instantiating Objects.

4.2 Can interfaces Inherit common Classes? Can interfaces inherit abstract classes?

Interfaces cannot inherit from ordinary classes.

Public class Animal {} public class Animal {typeAnimal cannot be a superinterface of Fly; Public interface extends Animal{void Fly (); }Copy the code

Interfaces cannot inherit abstract classes.

Public abstract class Airplane {} public abstract class Airplane {typeAirplane cannot be a superinterface of Fly; Error message public interface Fly extends Airplane{void Fly (); }Copy the code

This makes sense, since only static constants and abstract methods can be defined in interfaces, and neither ordinary nor abstract classes are so strict, so interfaces cannot inherit from either.

4.3 What happens when methods in the parent class of an implementation class are the same as methods in the interface?

4.3.1 Class inheritance under normal circumstances

In Java, a subclass of a class inherits all the methods and properties of its parent class that are decorated with the public and protected keywords.

Public class Animal {public voideat(){
		System.out.println("Animal eat"); } } public class Tiger extends Animal{ } public class TigerTest { public static void main(String[] args) { Tiger tiger =  new Tiger(); tiger.eat(); }} Animal eatCopy the code

4.3.2 Interface implementation under normal circumstances

In Java, when a class implements an interface, it implements all the methods in that interface.

// source code public interface Fly {void Fly (); } public class Eagle implements Fly { @Override public voidfly() {
		System.out.println("Eagle fly"); } } public class EagleTest { public static void main(String[] args) { Eagle eagle = new Eagle(); eagle.fly(); }} // Result Eagle flyCopy the code

4.3.3 Methods in the parent class of the implementation class are different from methods in the interface

Public class Animal {public voideat(){
		System.out.println("Animal eat");
	}
	
}

public interface Fly {
	
	void fly();
	
}

public class Vulture extends Animal implements Fly {

	@Override
	public void fly() {
		System.out.println("Vulture fly"); } } public class VultureTest { public static void main(String[] args) { Vulture vulture = new Vulture(); vulture.eat(); vulture.fly(); Animal eat Vulture flyCopy the code

Methods in the parent class of the implementation class are the same as methods in the interface

This usually doesn’t happen, unless a programmer is looking for trouble. But if it’s to understand the concept of interfaces, it’s worth a try. As Bruce Eckel, author of Thiking in Java, puts it:

I generally find that once you know about a feature, you often discover places where it is useful.

Once the method name is determined, we are left with the parameter list and return value type of the method. Next, we analyze the various cases:

The serial number The specific situation
1 The same parameter returns the same value
2 The same parameters, different return values
3 The same value is returned for different parameters
4 The return value varies with parameters

Ps: The assumption here is that the method names are the same.

4.3.4.1 If the parameters are the same, the Return Value is the same

Public class Animal {public voidhunt(){
		System.out.println("Animal hunt"); } } public interface Hunt { void hunt(); } public class Eagle extends Animal implements Hunt{ } public class EagleTest { public static void main(String[] args) {  Eagle eagle = new Eagle(); eagle.hunt(); }} Animal huntCopy the code

Conclusion: When the signature and return value of the method in the parent class of the implementation class are exactly the same as the signature and return value of the method in the interface, then the subclass may not explicitly implement the method in the interface. If, at this point, the implementation class does not explicitly implement the methods in the interface, then the methods in the parent class are called.

4.3.4.2 The same parameters, different Return values

Public class Animal {public voidhunt(){
		System.out.println("Animal hunt"); } } public interface Hunt { String hunt(); } // At this point, if The methods in The interface are not implemented, The development tool will prompt Thereturn types are incompatible forPublic class Eagle implements Animal Hunt{// Inherited Methods hunt.hunt (), Animal. Hunt (return typeIs incompatible with animal.hunt () Error message public Stringhunt() {return ""; }}Copy the code

Conclusion: The implementation class definition fails when the signature of the method in the parent class of the implementation class is the same as the signature of the method in the interface, but the return value is different. That is, there is no such class.

4.3.4.3 Different parameters, the same return value

Public class Animal {public voidhunt(){
		System.out.println("Animal hunt");
	}
	
}

public interface Hunt {

	void hunt(String place);
	
}

public class Eagle extends Animal implements Hunt{

	@Override
	public void hunt(String place) {
		System.out.println("Eagles hunt on the " + place);
	}
	
}

public class EagleTest {

	public static void main(String[] args) {
		Eagle eagle = new Eagle();
		eagle.hunt();
		eagle.hunt("grasslands"); }} // this is how the family helpedCopy the code

Conclusion: When the parameters of the method in the parent class of the implementation class are different from the parameters of the method in the interface, but the return value is the same, the implementation class needs to re-implement the method in the interface.

4.3.4.4 Different parameters lead to different return values

Public class Animal {public voidhunt(){
		System.out.println("Animal hunt");
	}
	
}

public interface Hunt {

	String hunt(String place);
	
}

public class Eagle extends Animal implements Hunt{

	@Override
	public String hunt(String place) {
		System.out.println("Eagles hunt on the " + place);
		return place;
	}
	
}

public class EagleTest {

	public static void main(String[] args) {
		Eagle eagle = new Eagle();
		eagle.hunt();
		System.out.println(eagle.hunt("grasslands")); }} // 查 看 原 文Copy the code

Conclusion: When the parameters and return values of the method in the parent class of the implementation class are different from the parameters and return values of the method in the interface, the implementation class needs to re-implement the method in the interface.

The reason why the above concept is not clear is because the definition of the class is not understood thoroughly:

Class name extends parent name implements interface name {attribute; Methods; }Copy the code

As you can see from the above definition, a subclass inherits its parent class and then implements the interface. The code of “4.3.4.1 Same parameters, Same Return Value” also confirms this, because if it is implemented first and inherited, then the Eagle class of “4.3.4.1 Same parameters, Same Return Value” needs to implement the method of interface Hunt, but it is not implemented here, and the development tool does not report an error, which indicates that, Methods in the Hunt interface are not explicitly defined in the Eagle class, so it is correct to assume that inferential subclasses inherit from the parent class before implementing the interface.

After you understand that the subclass inherits the parent class first and then implements the interface, the above conclusions are easy to understand, such as the conclusion of “4.3.4.2 Same parameters, Different Return Values” :

The implementation class definition fails when the signature of the method in the parent class of the implementation class is the same as the signature of the method in the interface, but the return value is different. That is, there is no such class.

Because the implementation class inherits from the parent class before implementing the interface, when the implementation class inherits from the parent class, it has defined a method whose signature is the same as the method signature in the interface. In this case, the only difference between the two methods is that the return value is different, and the difference in return value does not distinguish the two methods, that is, the condition of method overload is not met (the method name is the same, the parameter type or number is different), so the class cannot be defined. In the same way, this is why the Hunt methods in 4.3.4.3 and 4.3.4.4 need to be redefined in the Eagle class — the Eagle class does not implement the methods in the Hunt interface, All it has is a method in the Animal class that overloads the method in the Hunt interface.

4.4 Can Interfaces be Defined in Common Classes?

You can.

Public class Animal {interface Climb{}Copy the code
4.5 Can An Interface Be Defined?

You can.

Public interface Hunt {interface Kill{}}Copy the code
4.6 How do I Use private Interfaces defined in Common Classes?
Public class Animal {private Climb mClimb; public interface Hunt{ void hunt(); } private interface Climb{ void climb(); } public class ClimbImpl implements Climb{ @Override public voidclimb() {
			System.out.println("ClimbImpl climb");
		}
		
	}
	
	public Climb getClimb() {return new ClimbImpl();
	}
	
	public void setClimb(Climb climb){
		this.mClimb = climb;
		mClimb.climb();
	}
	
}

public class Eagle implements Animal.Hunt {

	@Override
	public void hunt() {
		System.out.println("Eagle hunt"); }} // The development tool will prompt ThetypeAnimal.Climb is not visible error Public class Tortoise.Climb {} public class Tortoise  void main(String[] args) { Animal animal = new Animal(); System.out.println(animal.toString()); Animal.Hunt hunt = new Eagle(); hunt.hunt(); //Climb cannot be resolved to atype// Climb climb = animal.getClimb(); animal.setClimb(animal.getClimb()); www.define_interface_in_class_one.Animal@7852e922 Eagle hunt ClimbImpl climbCopy the code

The final animal.setclimb (animal.getclimb ()) method is a bit of an obtruse, but the main point here is that you can actually use the private interface defined inside the class externally.

5. Interface application

There are so many usage scenarios of interfaces that it is impossible to analyze all of them. Next, let’s look at how interfaces can be used in real development from the dimensions of design patterns.

The factory method pattern is a commonly used creation pattern that does a good job of separating object creation from object usage and adding new types of product objects without affecting the original code. Next, let’s examine how interfaces can be applied in the factory method design pattern.

The factory method pattern is defined as follows:

Define an interface to create product objects in the factory parent class and let the subclass be responsible for producing concrete product objects. Define an interface for creating an object, Factory Method lets a class defer instantiation to subclassed.)

The structure diagram of the factory method pattern is as follows:

As can be seen from the above structure diagram, the factory method mode consists of four parts:

  1. Product (Abstract Product class)

Abstract product classes are the interfaces that define products and are the “parent classes” of product objects created by the factory method pattern.

  1. Concreteproducts (Concrete Products)

The concrete product class is the implementation class of the abstract product class, which implements the abstract product class and corresponds to the concrete factory class.

  1. Factory (Abstract Factory class)

The abstract factory class defines the interface to create the product class.

  1. ConcreteFactory (ConcreteFactory)

The concrete factory class is the implementation class of the abstract factory class, which implements the abstract factory class and is used to produce concrete products, corresponding to the concrete product class.

Next, we created a factory capable of producing mobile phones according to the factory method mode, with the structure diagram as follows:

Here is the specific code implementation:

Public interface Phone {void call(); } public class IPhone implements Phone { @Override public voidcall() {
		System.out.println("IPhone call");
	}

}

public class XiaoMi implements Phone {

	@Override
	public void call() {
		System.out.println("XiaoMi call");
	}

}

public class MeiZu implements Phone {

	@Override
	public void call() {
		System.out.println("MeiZu call");
	}

}

public interface PhoneFactory {
	
	Phone producePhone();
	
}

public class IPhoneFactory implements PhoneFactory {

	@Override
	public Phone producePhone() {
		return new IPhone();
	}

}

public class XiaoMiFactory implements PhoneFactory {

	@Override
	public Phone producePhone() {
		return new XiaoMi();
	}

}

public class MeiZuFactory implements PhoneFactory {

	@Override
	public Phone producePhone() {
		returnnew MeiZu(); } } public class PhoneFactoryTest { public static void main(String[] args) { PhoneFactory phoneFactory = new XiaoMiFactory(); Phone phone = phoneFactory.producePhone(); phone.call(); } // Execution result XiaoMi callCopy the code

It is also very convenient to add a new product class. You only need to create a new product class and a new factory, without any impact on the original code. For example, add the method of creating Huawei mobile phones for the factory:

Public class implements Phone {@override public voidcall() {
		System.out.println("HuaWei call");
	}

}

public class HuaWeiFactory implements PhoneFactory {

	@Override
	public Phone producePhone() {
		returnnew HuaWei(); } } public class PhoneFactoryTest { public static void main(String[] args) { PhoneFactory phoneFactory = new HuaWeiFactory(); Phone phone = phoneFactory.producePhone(); phone.call(); }} // Result HuaWei callCopy the code

Reference documentation
  1. Java Development Practice Classic
  2. Thinking in Java
  3. Design Patterns
  4. Java Tutorials
  5. Design Principles