Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Scala mixed with multiple inheritance, type hierarchy and collection

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "Scala mixed with multiple inheritance, type hierarchy and collection how to achieve", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how Scala mixes multiple inheritance, type hierarchy, and collections.

Using features to realize mix-in multiple inheritance

The equivalent of Java interface in Scala is Trait. Trait, which means traits and traits in English (called features in this article), is actually more powerful than interfaces. Unlike an interface, it can also define the implementation of properties and methods. Features in Scala are used to serve the modularization of a single-purpose functional module. By mixing this feature (module) group to achieve the functional requirements of various applications, Scala is also designed according to this idea.

In general, the class of Scala can only inherit a single parent class, but if it is a feature, it can inherit more than one. As a result, multiple inheritance is implemented. This can be thought of as basically the same function as the Ruby module. Just take a look at the following example. For ease of identification, the subsequent feature names are prefixed with the letter T. Features can inherit both classes and other features.

Class Person; / / the empty class used in the experiment. If the last Person class is used, the following / / PianoplayingTeacher class needs to construct the parameter trait TTeacher extends Person {def teach / / virtual method and does not implement} trait TPianoPlayer extends Person {def playPiano = {println ("I'm playing piano. ")} / / Real method has been implemented} class PianoplayingTeacher extends Person with TTeacher with TPianoPlayer {def teach = {println (" I'm teaching students. ")} / / define the implementation of virtual methods}

As shown above, multiple features can be mixed into a class by concatenating multiple with statements. * the inherited source uses extends, and the second one uses the with statement. As you know, there are abstract classes that can generate instances. Also note that it is not possible to create instances directly from features.

Then let's actually run it.

Scala > val T1 = new PianoplayingTeacher T1: PianoplayingTeacher = PianoplayingTeacher@170a650 scala > t1.playPiano I'm playing piano. Scala > t1.teach I'm teaching students.

In fact, as shown below, you can assign the respective characteristics of features to objects only when you create them.

Scala > val tanakaTaro = new Person with TTeacher with TPianoPlayer {| def teach = {println ("I'm teaching students.")}} tanakaTaro: Person with TTeacher with TPianoPlayer = $anon$1@5bcd91 scala > tanakaTaro playPiano I'm playing piano. Scala > tanakaTaro teach I'm teaching students.

Using features to easily realize aspect-oriented programming

After making full use of the features, we can easily implement the popular aspect-oriented programming (AOP).

First, the module Taction that represents the basic action method is declared with features.

Trait TAction {def doAction}

Then, as an added aspect, define the feature TBeforeAfter with pre-processing and post-processing.

Trait TBeforeAfter extends TAction {abstract override def doAction {pre-processing of println ("/ entry before-action") / / doAction super.doAction / / call the post-processing of the original processing println ("/ exit after-action") / / doAction}

Override the virtual method with the abstract override def doAction {} statement above. Specifically, super.doAction is the key, calling the doAction method of TAction. The principle is that because doAction is a virtual method, what is actually executed is the method defined in the entity class being called.

Then implement the actual executed entity class RealAction as a subclass of TAction.

Class RealAction extends TAction {def doAction = {println ("* * real action examples! * *")}}

And then execute it.

Scala > val act1 = new RealAction with TBeforeAfter act1: RealAction with TBeforeAfter = $anon$1@3bce70 scala > act1.doAction / entry before-action * * real action customers! * * / exit after-action

It's not fun to do this alone, then define other aspects for him, and then add those aspects to the methods of the same object. Then define an aspect that executes the source method twice.

Trait TTwiceAction extends TAction {abstract override def doAction {for (I val act2 = new RealAction with TBeforeAfter with TTwiceAction act2: RealAction with TBeforeAfter with TTwiceAction = $anon$1@1fcbac1 scala > act2.doAction / entry before-action * * real action stories! * * / exit after-action = > No.1 / entry before-action * * real action stories! * * / exit after-action = = > No.2

Along with the before/after action of the original method, it is executed twice each. Then reverse the mixing order and try again.

Scala > val act3 = new RealAction with TTwiceAction with TBeforeAfter act3: RealAction with TTwiceAction with TBeforeAfter = $anon$1@6af790 scala > act3.doAction / entry before-action * * real action stories! * * = > No.1 * * real action stories! * * = > No.2 / exit after-action

After this execution, the original implementation is executed twice in a loop, but before/after is executed only once outside the loop as a whole. This is done in the order defined by the with statement, and it's not surprising to know how this works. The order in which Scala features are so mixed is the same as aspects of AspectJ and interceptor of Spring.

This is not only a before and after action, as long as you change the implementation of the feature, you can dynamically add various aspects to the original object, and the reader can also try a variety of other situations.

Functions that can be achieved through Decorator or Template Method patterns in Java can be easily achieved through features in Scala. From this can be extended, by inserting hooks into the original method, that is, the so-called interceptor-style aspect-oriented approach, various aspects can be easily componentized through features.

If you think of how strongly typed and static Scala is, you will be able to understand the special features of adding new functions through features.

How much flexibility it brings to him.

Type system of Scala (basic types)

The basic data that can be used in Scala is defined in the form of classes, so there is no difference between basic types and user-defined types. Having said that, Scala provides a class definition group that corresponds to the data type of Java (figure 4mur1). These are by no means wrapper classes, and they will be mapped to Java bytecode after compilation, so there is absolutely no performance problem.

Fig. 4 the class groups corresponding to the basic types of Scala

As shown in the following example program, you can respond to various messages (methods) for integer object 7. You can either execute the toString method to convert to a string, or you can use to, which executes Int = > Range. Incidentally, 7 to 20 is equivalent to 7.to (20), and the execution result of this method is Range (7, 8, 9,... 19, 20). Foreach ((I) = > print (I)) is applied to this scope object, and print _ is equivalent to the anonymous function (I) = > print (I) of one parameter.

Scala > 7.toString res2: java.lang.String = 7 scala > 7 to 20 foreach (print _) 7891011121314151617181920

In fact, Scala defines type aliases that exist in order to be compatible with Java base types in the Predef singleton object that is automatically introduced by the compiler. For example, boolean, char, byte, short, int, long, float, double are defined, and these aliases actually refer to Scala classes such as Scala.Boolean,Scala.Char,Scala.Byte. If possible, in order to raise the awareness that "all data is objects in Scala," it is recommended that you try to use the original class names such as Int, Boolean, Float, and so on.

However, there is no type conversion operator in Scala, but an equivalent method asInstanceOf [X] is defined in the base class Any of all classes. In this way, you can convert the type to X. The isInstanceOf [X] method equivalent to the instanceof operator is also defined in the Any class.

The basic structure of the 4-2Scala class hierarchy of the graph

In particular, the set types under Iterable in this class level play an important role in functional programming. Among them, the class levels of the two series of mutable and immutable basically show a mirror relationship, and of course, the group of immutable set types can give full play to the function of functional language.

At this point, I believe you have a deeper understanding of "how Scala mixes multiple inheritance, type hierarchy, and collection". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report