Talking about "combination" and "inheritance" on the new language platform

Source: Internet
Author: User
Tags traits

For a long time, an important tenet of OO programming idea is that it is widely accepted and recognized that it is a multi-use combination and less inheritance. This "seems" to have been impacted by the introduction of trait (trait) in Scala, and you can see that in many Scala code there are cases where a class is mixed (appended) with a new feature by inheriting multiple trait. Many of these cases are not or are not recommended in the traditional OO language (e.g. Java) because it seems that it is really abusing inheritance.

As a simple example, the log function is a very common requirement, and traditional Java programs Add this functionality to a class in a "combined" way, that is, declaring a logger instance as a field in a class, and then using it everywhere in the class. This is almost the only option in a single-inheritance programming language like Java, and it is clear that you cannot make your class occupy only a single parent for a log printing function, even if your class does not have any parent class, and it is a strange thing to have a class that inherits a logging parent class.

In Scala, things have changed, and because trait's multi-inheritance feature makes it natural and common for a class to inherit multiple traits, it provides a new way for programmers to "mix new features into a class." Many of the places used in Java are replaced by "inheritance" based on traits. The same is true of the above log function, which is commonly implemented in Scala:

trait Logger {  def log(msg: String): Unit = {    println(msg)  }}class DataAccess extends Logger{    def query(in: String) = {      log(in)  }}new DataAccess().query("Test")

The first thing to explain here is that to let dataaccess inherit a logger seems to be a bit abrupt and weird, and if DataAccess has other parent classes or traits, we logger on the last append of the WITH statement may seem a lot more natural.

Well, back to the Scala version of this implementation, a programmer who has just turned to Scala from Java will feel uncomfortable with the traditional dogma he accepted in the past telling him that this place should use combinations rather than inheritance! But the Scala community is generally written in such a way that we need to think deeply. First of all, we need to figure out a question, in the traditional OO language why to advocate multi-use combination of less inheritance, abuse of inheritance of what is the harm?

A common recognition is that "misuse" of inheritance will break the envelope, and remember that our qualifications are "abusive". In languages that support multiple inheritance, the cost of inheriting a class is very low, low to negligible, which is one of the main reasons for the misuse of inheritance, the most direct consequence of misuse of inheritance is the destruction of encapsulation, the reason is simple, when the subclass inherits the parent class, it will "inherit" all classes and methods of the parent class. If a class is naturally a subclass of another class from its core intent and design, there is no way to break encapsulation, and the real problem is that a class should not be intended or designed to be a subclass of a class, but it needs to use or rely on part of the functionality of the class. Using inheritance at this point exposes all the fields and methods of the parent class to the child class. If you use a combination, you limit the occurrence of this situation to some extent.

Above we have analyzed whether two judgments are an important basis for abusing inheritance:

    1. If a class is naturally a subclass of another class from its core intent and design, this inheritance is natural and does not have the notion of destroying encapsulation.
    2. In a language that allows multiple inheritance, if a class needs to use "all" fields and methods from another parent class (trait), or conversely, assigning all members of a parent class (trait) to another class, if there is no sense of vainly disobey from the design intent and representation of the two classes, then The use of inheritance is justified at this time, without the suspicion of damaging encapsulation.

There is a lot of subtext to the 2nd, and we emphasize the "all" field and method, which is an important sign of the "is-a" relationship, and if not all, that inheritance is questionable, usually, there are two possibilities:

    1. You should never inherit.
    2. Is your paternal (trait) responsibility not a single one? Do you need to re-create more of a single parent (trait), and then choose the appropriate parent (trait) to inherit from?

Based on the above principles, we analyze two cases, the first one is the logger trait in the previous instance code, we can say that this is an absolute single trait, all the classes that want to inherit it are also very single: the ability to get log output, in which case the use of inheritance has no side effects, Although this to from the single successor language just turn over the programmer still feel some "in the mind is not steadfast", but careful analysis of a turn will find not touched what red line, so should be able to quickly adapt to this writing.

The other is very similar to logger, but in my opinion it is a negative case, that is, the inheritance of the Config class as seen in many code:

 trait Config {  Private ValConfig = Configfactory.load ()Private ValHttpconfig = Config.getconfig ("http")Private ValDatabaseconfig = Config.getconfig ("Database")ValHttphost = httpconfig.getstring ("Interface")ValHttpport = Httpconfig.getint ("Port")ValJdbcurl = databaseconfig.getstring ("url")ValDbUser = databaseconfig.getstring ("User")ValDbpassword = databaseconfig.getstring ("Password")} class httpservice extends Config {...} class databaseservice extends Config {...}

Similar to the above code appears in many programs, the designer hopes that by inheriting the Config allows a class to easily get the value of the configuration item, unlike Logger, config contains all the configuration items of the entire application, no class needs and should inherit all of its fields, This contradicts the 2nd important principle we mentioned earlier, which also severely destroys the encapsulation of config maintenance. The Httpservice and Databaseservice in the code can also explain this from the side, each of which is concerned with HTTP and database-related configurations, and there is no reason for other configuration items to be exposed to them. It is relatively elegant to encapsulate these configuration items in an object, which can be obtained as a variable when a configuration item needs to be used.

Let's summarize:

For those who inherit from the traditional OO language to support the multi-successor language programmer, you should "want to open a bit":), flowers open to fold straight, if a class is to obtain a certain aspect of the "characteristics", more not, less can not, then be assured to inherit the "trait" it. In addition, you should be cautious about each succession, inheritance is always a need to be vigilant, especially in the language that allows multiple inheritance.

Talking about "combination" and "inheritance" on the new language platform

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.