Let's start with the most authentic definition
If there is object o2 of type T for each object o1 of type S, so that when all object o1 defined by T is replaced by o2, the behavior of program P does not change, then type S is a subtype of type T.
Let's look at a simple definition:
All references to base classes must be able to use objects of their subclasses transparently.
Let's take a look at the uml diagram
public abstract class AbstractGun { //What's the gun for? Kill the enemy! public abstract void shoot(); } //The implementation classes of pistol, rifle and machine gun are shown in listing 2-2. Code listing 2-2 implementation class of pistol, rifle and machine gun public class Handgun extends AbstractGun { //The pistol is easy to carry and has a short range @Override public void shoot() { System.out.println("Pistol shooting..."); } } public class Rifle extends AbstractGun{ //The characteristics of rifles are long range and powerful public void shoot(){ System.out.println("Rifle shooting..."); } } public class MachineGun extends AbstractGun{ public void shoot(){ System.out.println("Machine gun fire..."); } } //With guns, there must be soldiers who can use these guns, and their source programs, such as soldiers' implementation classes public class Soldier { //Defining a soldier's gun private AbstractGun gun; //Give the soldier a gun public void setGun(AbstractGun _gun){ this.gun = _gun; } public void killEnemy(){ System.out.println("The soldiers began to kill the enemy..."); gun.shoot(); } } //It is defined that soldiers use guns to kill enemies, but this gun is abstract. Whether it is a pistol or a rifle needs to be determined by setGun method before going to the battlefield (that is, in the scene) public class Client { public static void main(String[] args) { //Produce Sanmao, the soldier Soldier sanMao = new Soldier(); //Give Sanmao a gun sanMao.setGun(new Rifle()); sanMao.killEnemy(); } }
Some special subclasses will inevitably be encountered in the project, so it is recommended to use aggregation or combination
For example, as follows
public class ToyGun extends AbstractGun { //The toy gun can't shoot, but the compiler requires to implement this method. What should I do? Make up one! @Override public void shoot() { //If the toy gun can't shoot, this method will not be realized } } public class Client { public static void main(String[] args) { //Produce Sanmao, the soldier Soldier sanMao = new Soldier(); sanMao.setGun(new ToyGun()); sanMao.killEnemy(); } }
In this case, the following methods are recommended
Let's also look at the uml diagram
public class AUG extends Rifle { //Sniper guns carry a precise telescope public void zoomOut(){ System.out.println("Look at the enemy through a telescope..."); public void shoot(){ System.out.println("AUG Shooting..."); } } public class Snipper { public void killEnemy(AUG aug){ //First of all, look at the situation of the enemy. Don't kill the enemy. You will also be killed by others aug.zoomOut(); //Start shooting aug.shoot(); } } public class Client { public static void main(String[] args) { //Generate Sanmao, the sniper Snipper sanMao = new Snipper(); sanMao.setRifle(new AUG()); sanMao.killEnemy(); } }
In order to meet the design requirements of the "Richter replacement" principle, the subclass cannot have too much personality. When the subclass overloads the method of the parent, the input parameter should be broader, greater than or equal to the parent, and the return value should be contracted, less than or equal to the parent. Let's take a look at the specific code description
public class Father { public Collection doSomething(HashMap map){ System.out.println("Parent class is executed..."); return map.values(); } } public class Son extends Father { //Enlarge input parameter type public Collection doSomething(Map map){ System.out.println("Subclass is executed..."); return map.values(); } } public class Client { public static void invoker(){ //Where the parent exists, the child should be able to exist Father f = new Father(); HashMap map = new HashMap(); f.doSomething(map); } public static void main(String[] args) { invoker(); } }
Welcome to my official account.