简体   繁体   English

抽象类中的类型参数

[英]Type Parameters in `abstract class`

Given: 鉴于:

scala> abstract class Foo[A] {
     |   def f: A
     | }
defined class Foo

, and an implementation ,以及一个实现

scala> class FooImpl extends Foo[Any] {
     |   def f: Any = "foo"
     | }
defined class FooImpl

and then an instantiation 然后实例化

scala> new FooImpl().f
res0: Any = foo

res0 has type Any , as I'd expect since FooImpl uses Any as its type parameter to Foo . 正如我所期望的那样, res0具有Any类型,因为FooImpl使用Any作为其Foo类型参数。

And, given a second implementation: 并且,给出第二种实现:

scala> class FooImpl2 extends Foo[Any] {
     |   override def f= "foo"
     | }
defined class FooImpl2

and an instantiation and call to f : 以及实例化并调用f

scala> new FooImpl2().f
res1: String = foo

Why is res1 's type a String ? 为什么res1的类型为String

Whereas, given: 鉴于:

scala> def g[A](x: A):A = x
g: [A](x: A)A

I can pass y , an Int : 我可以通过y ,一个Int

scala> val y: Int = 55
y: Int = 55

to g g

scala> g[AnyVal](y)
res3: AnyVal = 55

and get back an AnyVal . 并返回AnyVal

Finally, 最后,

scala> g(55)
res5: Int = 55

returns an Int , as expected. 按预期返回Int

However, I would've expected FooImpl2#f to have returned an Any given FooImpl2 's extends Foo[Any] . 但是,我期望FooImpl2#f返回Any给定FooImpl2extends Foo[Any]

Why not? 为什么不?

When you override a member of an abstract class or trait, you are allowed to narrow its type to something more specific. 当您覆盖抽象类或特征的成员时,可以将其类型缩小为更具体的类型。 It doesn't appear that way here, because you're relying on type inference for override def f = "foo" , but it's really override def f: String = "foo" . 它不会出现这样在这里,因为你依靠的类型推断override def f = "foo" ,但它确实override def f: String = "foo"

This is legal: 这是合法的:

abstract class Foo[A] {
  def f: A
}

class FooImpl2 extends Foo[Any] {
  override def f: String = "foo"
}

String still conforms to the type parameter A = Any , but f has been refined in FooImpl2 to String . String仍然符合类型参数A = Any ,但是fFooImpl2已经细化为String

Here is an example without the type parameter: 这是一个没有类型参数的示例:

abstract class A { def f: Any }
class B extends A { override def f: String = "a" }

g[AnyVal](y) is a just very different example. g[AnyVal](y)是一个非常不同的示例。 Since you are manually supplying the type parameter of AnyVal to g , you are asking the compiler to make sure y is AnyVal , but it doesn't matter if it is some more specific type (a more specific type returned by method will always be up-cast to the return type). 由于您正在向g手动提供AnyVal的类型参数, AnyVal您要求编译器确保yAnyVal ,但是它是否是更特定的类型并不重要(方法返回的更特定的类型将始终是up -cast到返回类型)。 In FooImpl2 you are simply changing the signature of f . FooImpl2您只需更改f的签名。

When you override a method, you can make it return more specific type. override方法时,可以使其返回更特定的类型。 In this line 在这条线

override def f= "foo"

you didn't specify return type and it was inferred to be String 您未指定返回类型,因此推断为String

A subclass can narrow the return types of the methods that it overrides. 子类可以缩小其覆盖的方法的返回类型。
The return type of f in Foo[Any] is Any . Foo[Any]f的返回类型为Any FooImpl2 is a subtype of Foo[Any] and you didn't specify f s return type so the compiler infers that it is String , which is a subtype of Any and thus satisfies all constraints. FooImpl2Foo[Any]的子类型,您没有指定f s返回类型,因此编译器推断它是String ,它是Any的子类型,因此满足所有约束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM