Scala-associated objects to orphaned objects
Although Scala is built on a JVM, there are many differences from Java, but one important difference is that Scala is more object-oriented (purely object-oriented) than Java, and the most obvious use case is that all operators in Scala are methods (the subject of operator-oriented objects).
The associated object/orphaned object is also a reflection of Scala as a purely object-oriented language.
orphaned objects
Let's look at an example.
object Test{ "helloworld" def helloworld(): Unit = { println("helloworld") }}
When used, it gives a feeling similar to the following code
publicclass Test { publicstatic"helloworld"; publicstaticvoidhelloworld() { System.out.println("helloworld"); }}
So, we can access the a
fields or methods in the following way helloworld()
Test.aTest.helloworld()
This will give people the above error, but this is not the case, the test here is actually an object (global singleton), see the following example
object Test{ var"helloworld" def helloworld(): Unit = { println("helloworld") } def main(args: Array[String]) { println(Test) }}
The results of running in REPL are as follows:
D:\> scalac Test.scalaD:\> scala TestTest$@3eb25e1aD:\>
To this, summarize, for object Test{...}
, we are in use Test.field
or Test.method
when, Test
is actually a global singleton object, and not a class, the following through the anti-compilation of the class file to look at the specific details
Scala source code
object Test{ "helloworld" def helloworld(): Unit = { println("helloworld") } }
Compiled Java code
Fictional class:
ImportScala. Predef.; Public Final class Test${ Public Static Finalmodule$;PrivateString A;Static{New(); } PublicStringa() {return ThisA } Public voida_$eq(String x$1) { This. A = x$1; } Public void HelloWorld() {predef: Module$.println ("HelloWorld"); }Privatetest$ () {module$ = This; This. A ="HelloWorld"; }}
Associated class
publicclass Test{ publicstaticvoidhelloworld() { Test..MODULE$.helloworld(); } publicstaticvoid a_$eq(String paramString) { Test..MODULE$.a_$eq(paramString); } publicstatica() { return Test..MODULE$.a(); }}
From the defective anti-compilation code above, we can see that all the calls on test are finally acting on the singleton object MODULE$
, the entire logical mechanism is as follows
Transfer Entry (TEST.XXXX)
↓
Associated Class (static method)
↓
Fictitious class (Singleton object module$)
Associated objects
Orphaned objects with associated classes are called associated objects, and the associated classes have the following relationship with the associated objects:
The following creates a companion class for the orphaned object test
import scala.beans.BeanPropertyclass Test{ @BeanPropertyvar"zhangsan" def func1() { println("func1") }}object Test{ var"helloworld" def helloworld(): Unit = { println("helloworld") } }
With the previous basis, direct analysis of the compiled source code
Fictional class:
ImportScala. Predef.; Public Final class Test${ Public Static Finalmodule$;PrivateString A;Static{New(); } PublicStringa() {return ThisA } Public voida_$eq(String x$1) { This. A = x$1; } Public void HelloWorld() {predef: Module$.println ("HelloWorld"); }Privatetest$ () {module$ = This; This. A ="HelloWorld"; }}
Associated classes:
Public classtest{PrivateString name ="Zhangsan"; Public Static void HelloWorld() {Test: Module$.helloworld (); } Public Static voida_$eq(String paramstring) {Test.. Module$.a_$eq (paramstring); } Public StaticStringa() {returnTest.. MODULE$.A (); } PublicStringname() {return This. Name; } Public voidname_$eq(String x$1) { This. Name = x$1; } Public void SetName(String x$1) { This. Name = x$1; } Public void func1() {predef: Module$.println ("Func1"); } PublicStringGetName() {returnName (); }}
From the above anti-compiled code, for the companion class and the associated object of the Scala code, compiled, still two class files, in the associated object and the properties and methods are still compiled according to the previous rules, but in the associated class, the properties and methods are different, It is placed in the class file of the associated class and is non-static, which means that the properties and methods are instance-dependent, which is expected.
So, for Test,
valnew Testvalnew Testtest1 != test2
The test1
object test2
is different from the example, but
Test.equals(Test)Test == Test
Is true because the test is pointed to globally unique singleton objects MODULE$
.
Summarize
The properties and methods of the associated object still point to the global singleton objectMODULE$
The properties and methods of the associated class are defined as Object-dependent.
Associated objects are usually used in a container of singleton objects or tool methods
Scala Learning Notes-companion objects to orphaned objects