Array of complex type elements

I have been playing around with composite types lately and I recently tried using the following code:

import scala.reflect._

object Main {

  def main(args: Array[String]) {
    val a1 = classTag[Int with String with Double].newArray(3)
    println(a1.mkString(" "))

    val a2 = classTag[String with Int with Double].newArray(3)
    println(a2.mkString(" "))

    val a3 = classTag[Double with Int with String].newArray(3)
    println(a3.mkString(" "))
  }

}

      

With the following output:

0 0 0
null null null
0.0 0.0 0.0

      

This is a little strange to me. Each of the array elements has access to three types of methods: Int, String, and Double. What is happening behind the scenes here? Are the constituent types actually instances of the first type? Can an explicit composite type? Does their use only happen when the types that make up the connection are related through inheritance and so on? Thank.

PS: I am using Scala 2.11.4

+3


source to share


1 answer


What is happening behind the scenes here? Connection types are instances of the first type?

Looking at the method newArray

as defined for ClassTag

:

override def newArray(len: Int): Array[T] =
   runtimeClass match {
     case java.lang.Byte.TYPE      => new Array[Byte](len).asInstanceOf[Array[T]]
     case java.lang.Integer.TYPE   => new Array[Int](len).asInstanceOf[Array[T]]
     /* snip */
     case _                        => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
   }

      

And then your type:

scala> classTag[Int with String with Double].runtimeClass
res4: Class[_] = int

      

It seems pretty clear how he comes to the conclusion to use the first type. runtimeClass

of Int with String with Double

- Int

, and the method newArray

uses runtimeClass

to create a new one Array

. Thus, it is Array

populated with default values Int

. Likewise for other combinations of orders.

Why an execution class Int

? Well, Int with String with Double

not an actual class, but it Int

is. The compiler's choice of which class to use cannot be arbitrary, so why not the first one?

Can a composite type be explicitly specified?

I'm not sure what you mean by that. If you think about it, then the compiler should use one type in this composition. What does explicit look like Int with String with Double

? What about Int with String with Double with Product with Process

? I do not know either.



Each of the array elements has access to methods of three types: Int, String and Double

They do, and yet they don't.

scala> val arr = classTag[Int with Process].newArray(3)
arr: Array[Int with Process] = Array(0, 0, 0)

scala> arr(0).exitValue()
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Process

      

You really just cheating the compiler, assuming that you have Array

these types, when in fact you do not (and can not, because nothing can be a subtype of both Int

, and so Process

).

Does their use only happen when the types that make up the connection are related through inheritance, etc.?

To a large extent, yes. I can't think if there is any situation in which you would ever want to try to construct these types directly. Their main use case is to ensure that a type inherits from other concrete types.

For example, a method that requires a parameter to inherit methods from two traits:

trait Hello { def hello = println("Hello") }

trait Bye { def bye = println("Bye") }

def greet(hb: Hello with Bye): Unit = { hb.hello; hb.bye }

class A extends Hello

class B extends Hello with Bye

scala> greet(new A)
<console>:15: error: type mismatch;
  found   : A
  required: Hello with Bye
          greet(new A)
                ^

scala> greet(new B)
Hello
Bye

      

+3


source







All Articles