Scala构造函数参数是否重复?

Scala构造函数参数是否重复?,scala,Scala,我只是偶然发现了一些我觉得很奇怪的情况。我很可能错过了这里显而易见的东西——无论如何,请帮我解决 考虑以下Scala repl脚本: scala> class X(val s: String) { def run=println("(X): "+s) } defined class X scala> class Y(s: String) extends X("MY "+s) { override def run=println("(Y): "+s) } defined class

我只是偶然发现了一些我觉得很奇怪的情况。我很可能错过了这里显而易见的东西——无论如何,请帮我解决

考虑以下Scala repl脚本:

scala> class X(val s: String) { def run=println("(X): "+s) }
defined class X

scala> class Y(s: String) extends X("MY "+s) { override def run=println("(Y): "+s) }
defined class Y

scala> new Y("fish").run
(Y): fish
在脚本中,我用class属性“val s”定义了一个class X。 然后我定义了一个类Y,它应该接受一个构造函数参数,并将其传递给X,它就是这样做的。为了显示差异,我修改了“s”,然后将其交给X(“MY”+s)

最后,我创建了一个新的Y并称之为“run”。这会将“fish”打印到控制台,因此很明显,类“X”的属性“s”已被我在“Y”中创建的新属性“s”遮挡

我用Scala 2.8和2.9.1尝试了这个方法,得到了相同的结果

应该是这样吗?如果我只想将构造函数参数从类传递到超类,而不想将参数存储在子类中,该怎么办?这里的惯例是什么


谢谢

如果不在子类的构造函数中使用该参数,则不会存储该参数。如果需要引用父参数而不是构造函数参数,请使用其他变量名

展示示例的课程:

class X(val s: String) { def run=println("(X): "+s) }
class Y(s: String) extends X("MY "+s) { override def run=println("(Y): "+s) }
class Z(s0: String) extends X("MY "+s0) { override def run=println("(Z): "+s) }
显示缺少存储的字节码(仅限构造函数):

//注意要存储的putfield
公共X(java.lang.String);
代码:
0:aload_0
1:aload_1
2:putfield#11//字段s:Ljava/lang/String;
5:aload_0
6:特别是#43//方法java/lang/Object。“:()V
9:返回
//注意putfield存储新的s(然后最终调用X的构造函数)
公共Y(java.lang.String);
代码:
0:aload_0
1:aload_1
2:putfield#29//字段s:Ljava/lang/String;
5:aload_0
6:新#16//类scala/collection/mutable/StringBuilder
9:dup
10:特别是19//方法scala/collection/mutable/StringBuilder。“”:()V
13:最不发达国家40//串我的
15:invokevirtual#25//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
18:aload_1
19:invokevirtual#25//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
22:invokevirtual#33//方法scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
25:44//方法X.“”:(Ljava/lang/String;)V
28:返回
//注意-没有putfield!
公共Z(java.lang.String);
代码:
0:aload_0
1:新#14//类scala/collection/mutable/StringBuilder
4:dup
5:特别是#17//方法scala/collection/mutable/StringBuilder。“”:()V
8:最不发达国家39//串我的
10:invokevirtual#23//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
13:aload_1
14:invokevirtual#23//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
17:invokevirtual#32//方法scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
20名:特别是43名//方法X.“”:(Ljava/lang/String;)V
23:返回

事实上,参数s隐藏了超类参数。重要的一点是,类参数(即主构造函数的参数)的范围是整个类。因此,在Y.run方法中,毫无疑问s指的是Y.s

这意味着,雷克斯一定是在野外活着的,正如雷克斯向你们展示的,这正是正在发生的事情

对于主构造函数参数,有三种选择:

  • var=>生成字段、getter和setter
  • val=>生成字段和getter
  • 这两个=>都不会在必要时生成字段(即方法中使用的参数),但不会生成getter/setter

感谢您的详细解释!Y中的类参数s将X中定义的val s阴影化。
// Note putfield to store s
public X(java.lang.String);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #11; //Field s:Ljava/lang/String;
   5:   aload_0
   6:   invokespecial   #43; //Method java/lang/Object."<init>":()V
   9:   return

// Note putfield to store new s (then eventually calls X's constructor)
public Y(java.lang.String);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #29; //Field s:Ljava/lang/String;
   5:   aload_0
   6:   new #16; //class scala/collection/mutable/StringBuilder
   9:   dup
   10:  invokespecial   #19; //Method scala/collection/mutable/StringBuilder."<init>":()V
   13:  ldc #40; //String MY 
   15:  invokevirtual   #25; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
   18:  aload_1
   19:  invokevirtual   #25; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
   22:  invokevirtual   #33; //Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
   25:  invokespecial   #44; //Method X."<init>":(Ljava/lang/String;)V
   28:  return

// Note - no putfield!
public Z(java.lang.String);
  Code:
   0:   aload_0
   1:   new #14; //class scala/collection/mutable/StringBuilder
   4:   dup
   5:   invokespecial   #17; //Method scala/collection/mutable/StringBuilder."<init>":()V
   8:   ldc #39; //String MY 
   10:  invokevirtual   #23; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
   13:  aload_1
   14:  invokevirtual   #23; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
   17:  invokevirtual   #32; //Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
   20:  invokespecial   #43; //Method X."<init>":(Ljava/lang/String;)V
   23:  return