Overview
Inheritance is a concept in object-oriented, in the drink refactoring series [7]--use delegation instead of inheritance in this article, my "parent-child relationship" describes inheritance, which is a relatively partial argument. Then I again in the UML class Diagram 6 big relations, described the inheritance is one kind "is a kind of" the relation, it is more inclined to the concept level, this kind of explanation more conforms to the inheritance essence. The 3 refactoring strategy to be discussed in this article is to extract the base class, extract the subclass, and combine the subclass with the inheritance related, if the understanding of the inheritance is deep enough, the 3 strategies should be handy.
Extract base class definitions: If more than one class has similar functionality, you should extract a base class and put common functionality in the base class. The initial relationship of the illustration
Left defines the department and employee classes, although these two classes have some common traits-"get annual cost", "Get Name".
What is the relationship between department and employee when you see this picture at the first glance? Normally, you might think that department and employee are an aggregation relationship.
From the characteristics of these two classes, they have something in common-"get annual cost", "Get a name".
What should we do if we want to reuse these common points? The use of inheritance, of course.
Take employee to inherit department? There is no semantic "is a kind of" relationship between department and employee. We can't always say "Employee is a kind of department" bar.
Well, this path doesn't make sense, so let's change the concept to understand department and employee Bar--party.
What's a party? In concept, the party represents a group, the group can be a department, can also be a person.
Time to sentence
As mentioned earlier, the inheritance relationship can be described by "is a kind of", now we use "is a kind of" to make a few sentences to try.
"Department is a kind of the party."
"Employee is a kind of the party."
Does the concept of "party" sound more fluent? I think it's fluent.
If you think it is not fluent, let's change a position to build 2 sentences, using passive sentences.
"Party can be a kind of department."
"Party can be a kind of employee."
Can "party" also be the abstract concept of department and employee? I still think it is (if you think not, I can not do it).
Identify relationships
After such a toss-up, we are finally able to witness the emergence of the following relationship.
Note that we still retain the aggregation relationship between the department and the employee.
If you look at these pictures, will it cause you to think?
Things that seem to have no particular relationship can be made by abstracting higher-level concepts and allowing them to have relationships at other levels.
Department and employee seem to have no inheritance, however, by abstracting out the concept of "party", let it department and employee produce another layer of relationship-the same as the party's subclass.
Example before refactoring
This code defines a dog class and defines two methods: Eatfood () and Grrom (), which represent the "feeding" and "training" behaviors respectively.
public class dog{public void Eatfood () { //Eat some food } public void Groom () { // Perform grooming }}
Eatfood () and groom () are the public behavior of most animals, and when a new animal class is appended, these two behaviors may also occur, and we should consider extracting the two behaviors to the base class. After refactoring
public class animal{public void Eatfood () { //Eat some food } public void Groom () { Perform grooming }}public class dog:animal{}
Tip: When extracting a base class, if there is only one class in the present, you need to analyze what is likely to happen in the future according to the scene, which is a good example of this.
Of course, you may not have to extract the base class so early, and wait until the code is repeated two or three times to extract it later.
Extract Subclass Definition: If a method or property of a base class is not required by all subclasses, these methods and properties should be extracted into subclasses. An illustration
Some people may think that the more methods or properties in the base class, the better, this way the class requires very little code to accomplish a lot of functions.
When we define a method or property in a base class, it is important to determine the responsibility of the base class beforehand.
Early return
The animal class defines 4 methods: Eat (), run (), Fly (), and Swim (), respectively, indicating eating, running, flying, and planktonic behavior.
It is true that all animals eat, but there is basically no surface and air in the world, do you think this is the legendary dragon?
2nd back
Now that you have added a class mammal, it inherits the animal class.
Eat () and run () are common behaviors of mammals, and Fly () and swim () are not capable of all mammals.
3rd back
Enrich our animal world and add birds and fish ( mammals are not so lonely at last, they can eat seafood and roast chicken).
We don't specialize, we recognize mammal, bird and fish from generalization.
In general, Mammal has eat () and run () behavior, Bird has eat () and fly () behavior, and fish has eat () and swim () behavior.
If the graph is shown in code, the amount of code will be very small.
Although using inheritance can reduce the amount of code, it can be used to some extent to achieve the purpose of code reuse, but this does not mean accuracy, nor does it imply lower complexity.
The above describes the "inaccuracy", that is, the behavior of subclasses is not so accurate, that is, the base class is imposed on subclasses.
Then, let's look at the complexity, for example, from two angles, we can judge complexity:
- Total number of methods for base class + subclass: Altogether 16 methods
- Total number of methods per subclass: Each subclass has 4 methods
4th back
Combining the following diagram, we compare the complexities of these two approaches:
- Total number of methods for base class + subclass: Altogether 7 methods
- Total number of methods per subclass: Each subclass has 2 methods
In quantitative terms, the complexity of these two approaches is self-evident. Final return
After grinding for so long, use a picture to represent the refactoring strategy of "extracting subclasses" (green means that before refactoring, red indicates refactoring).
Example before refactoring
The registration class describes the students ' choice of course, and there are two types of courses available to students-enrolled and unregistered.
public class registration{Public nonregistrationaction Action {get; set;} Public decimal Registrationtotal {get; set;} public string Notes {get; set;} public string Description {get; set;} Public DateTime registrationdate {get; set;}} public class nonregistrationaction{ }
The properties of the registration class Nonregistrationaction and notes are only used in unregistered scenes, so you can consider extracting these two attributes into subclasses. After refactoring
The Nonregistration class is appended to the refactoring, so the division of responsibilities is clear: the registration class corresponds to the registered course selection scene, and the Nonregistration class corresponds to the non-registered course selection.
public class registration{Public decimal registrationtotal {get; set;} public string Description {get; set;} Public DateTime registrationdate {get; set;}} public class nonregistration:registration{Public nonregistrationaction Action {get; set;} public string Notes {get; set;}} public class nonregistrationaction{ }
Tip: When defining methods and properties in a base class, make sure they are "generic".
Merge Subclass Definitions: When all the method properties of a subclass are fully applicable to the base class, you should extract the methods and properties to the basis class, and remove the subclasses.
This refactoring strategy is relatively simple, we do not show, the direct use of examples to explain it , a little sleepy.
Example before refactoring
This code defines two classes: website and studentwebsite, respectively, "website" and "Student Site" (Do you have an adult site?). ) 。 Studentwebsite inherits from the Website,studentwebsite extension of a IsActive property, which indicates "whether active".
public class website{Public string Title {get; set;} public string Description {get; set;} Public ienumerable<webpage> Pages {get; set;}} public class studentwebsite:website{Public bool IsActive {get; set;}} public class webpage{ }
After refactoring
In fact, the IsActive property is fully applicable to all website instances, so there is no need to declare a studentwebsite class individually, you can define the IsActive attribute to the website class, and remove the Studentwebsite class (Does my " Adult website "Say no there is no?" )
public class website{Public string Title {get; set;} public string Description {get; set;} Public ienumerable<webpage> Pages {get; set;} public bool IsActive {get; set;}} public class webpage{}
Tip: Do not blindly create subclasses, and do not blindly define methods and properties in subclasses, it is not easy to use the base class.
Drink Remodeling Series [11]--Extract base class, extract subclass, merge subclass