4, The beauty of design patterns - 04| theory 2: what programming problems can encapsulation, abstraction, inheritance and polymorphism solve respectively?
Encapsulation, abstraction, inheritance and polymorphism are the key characteristics of object-oriented programming and object-oriented programming language. For these four characteristics, it is not enough to know their definitions. We also need to know the significance and purpose of each characteristic and what programming problems they can solve.
I Encapsulation
Encapsulation mainly focuses on how to hide information and protect data, while abstraction focuses on how to hide the specific implementation of methods, so that callers only need to care about what functions are provided by methods, and do not need to know how these functions are implemented.
Encapsulation is also called information hiding or data access protection. By exposing limited access interfaces, a class authorizes external users to access internal information or data only through the methods provided by the class (or called functions).
Encapsulation requires the programming language to provide syntax support for access control. private, public and other keywords are the access control syntax in the Java language.
Encapsulation can ensure that the values inside the object are not disturbed by the outside.
II Abstraction
In object-oriented programming, we often use two syntax mechanisms: interface class (such as interface keyword syntax in Java) or abstract class (such as abstract keyword syntax in Java) provided by programming language to realize the feature of abstraction.
The concept of abstraction is a very general design idea, which can not only be used in object-oriented programming, but also be used to guide architecture design. Moreover, this feature does not need the programming language to provide special syntax mechanism to support. It only needs to provide the very basic syntax mechanism of "function" to realize the abstract feature. Therefore, it has no strong "specificity" and is sometimes not regarded as one of the features of object-oriented programming.
III Inheritance
Inheritance is used to represent the is-a relationship between classes. For example, a cat is a mammal. In terms of inheritance relationship, inheritance can be divided into two modes, single inheritance and multi inheritance. Single inheritance means that a subclass inherits only one parent class, and multiple inheritance means that a subclass can inherit multiple parents. For example, a cat is both a mammal and a reptile.
In order to implement inheritance, the programming language needs to provide special syntax mechanisms to support it. For example, Java uses the extends keyword to implement inheritance, C + + uses a colon (class B: public a), Python uses parentheses (), and Ruby uses <. However, some programming languages only support single inheritance and do not support multiple inheritance, such as Java, PHP, c#, ruby, etc., while some programming languages support both single inheritance and multiple inheritance, such as C + +, Python, Perl, etc.
One of the biggest benefits of inheritance is code reuse. If the two classes have some of the same properties and methods, we can extract these same parts into the parent class and let the two subclasses inherit the parent class. In this way, the two subclasses can reuse the code in the parent class to avoid repeated writing of the code. However, this is not unique to inheritance. We can also solve the problem of code reuse in other ways, such as using composition relationship instead of inheritance relationship.
IV Polymorphism
Polymorphism is a subclass that can replace the parent class. When the actual code runs, it calls the subclass method.
For the implementation of polymorphism, in addition to the implementation of "inheritance plus method rewriting", we also have two other common implementation methods, one is using interface class syntax, the other is using duck typing syntax. However, not every programming language supports interface classes or duck typing. For example, C + + does not support interface class syntax, while duck typing is only supported by some dynamic languages, such as Python and JavaScript.
1. Interface implementation
public interface Iterator { boolean hasNext(); String next(); String remove(); } public class Array implements Iterator { private String[] data; public boolean hasNext() { ... } public String next() { ... } public String remove() { ... } //... Omit other methods } public class LinkedList implements Iterator { private LinkedListNode head; public boolean hasNext() { ... } public String next() { ... } public String remove() { ... } //... Omit other methods } public class Demo { private static void print(Iterator iterator) { while (iterator.hasNext()) { System.out.println(iterator.next()); } } public static void main(String[] args) { Iterator arrayIterator = new Array(); print(arrayIterator); Iterator linkedListIterator = new LinkedList(); print(linkedListIterator); } }
2. Inheritance implementation
public class DynamicArray { private static final int DEFAULT_CAPACITY = 10; protected int size = 0; protected int capacity = DEFAULT_CAPACITY; protected Integer[] elements = new Integer[DEFAULT_CAPACITY]; public int size() { return this.size; } public Integer get(int index) { return elements[index];} //... Omit n multiple methods public void add(Integer e) { ensureCapacity(); elements[size++] = e; } protected void ensureCapacity() { //... If the array is full, expand the capacity Code omission } } public class SortedDynamicArray extends DynamicArray { @Override public void add(Integer e) { ensureCapacity(); int i; for (i = size-1; i>=0; --i) { //Ensure that the data in the array is in order if (elements[i] > e) { elements[i+1] = elements[i]; } else { break; } } elements[i+1] = e; ++size; } } public class Example { public static void test(DynamicArray dynamicArray) { dynamicArray.add(5); dynamicArray.add(1); dynamicArray.add(3); for (int i = 0; i < dynamicArray.size(); ++i) { System.out.println(dynamicArray.get(i)); } } public static void main(String args[]) { DynamicArray dynamicArray = new SortedDynamicArray(); test(dynamicArray); // Print results: 1, 3, 5 } }
3. Duck typing implementation
The way duck typing implements polymorphism is very flexible. The Logger and DB classes have no relationship, neither inheritance relationship nor interface and implementation relationship. However, as long as they both have a record() method defined, they can be passed to the test() method, and the corresponding record() method will be executed during actual operation.
In other words, as long as two classes have the same method, polymorphism can be realized without any relationship between the two classes. This is the so-called duck typing, which is a unique syntax mechanism of some dynamic languages. For static languages such as Java to realize polymorphism through inheritance, there must be an inheritance relationship between the two classes. To realize polymorphism through interface, the class must realize the corresponding interface.
class Logger: def record(self): print("I write a log into file.") class DB: def record(self): print("I insert data into db. ") def test(recorder): recorder.record() def demo(): logger = Logger() db = DB() test(logger) test(db)
V Key review
1. About packaging properties
Encapsulation is also called information hiding or data access protection. By exposing limited access interfaces, the class authorizes external users to access internal information or data only through the methods provided by the class. It requires the programming language to provide permission access control syntax, such as private, protected and public keywords in Java. The significance of the encapsulation feature is to protect the data from being modified at will and improve the maintainability of the code; On the other hand, only a limited number of necessary interfaces are exposed to improve the ease of use of the class.
2. About abstract properties
Encapsulation mainly talks about how to hide information and protect data. That abstraction is how to hide the specific implementation of the method, so that users only need to care about what functions the method provides, and do not need to know how these functions are implemented. Abstraction can be implemented through interface classes or abstract classes, but it does not need special syntax mechanisms to support it. The significance of abstract existence, on the one hand, is to improve the scalability and maintainability of the code, modify the implementation without changing the definition and reduce the scope of code change; On the other hand, it is also an effective means to deal with complex systems, which can effectively filter out unnecessary information.
3. About inheritance properties
Inheritance is used to represent the is-a relationship between classes. It can be divided into two modes: single inheritance and multi inheritance. Single inheritance means that a subclass inherits only one parent class, and multiple inheritance means that a subclass can inherit multiple parents. In order to implement inheritance, programming languages need to provide special syntax mechanisms to support it. Inheritance is mainly used to solve the problem of code reuse. 4. About polymorphism
4. About polymorphism
Polymorphism is a subclass that can replace the parent class. When the actual code runs, it calls the subclass method. Polymorphism also requires programming languages to provide special syntax mechanisms, such as inheritance, interface classes and duck typing. Polymorphism can improve the scalability and reusability of code. It is the code implementation basis of many design patterns, design principles and programming skills.