如何在Scala中扩展抽象类并使用抽象构造函数 [英] How to extend an abstract class in scala and use the abstract constructor

查看:67
本文介绍了如何在Scala中扩展抽象类并使用抽象构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有抽象类A

abstract class A{

def this(obj:Object){
  this()
  obj match{
    case s:String => stringMethod(s)
    case n:Int => intMethod(n)
  }

  def stringMethod(s:String)

  def intMethod(n:Int)
}

我有一个扩展此类的课程

and I have a class that extends this class

class B(obj:Object) extends A(obj){
  var s:String = null

  def stringMethod(s:String){
    this.s = s
  }

  def intMethod(n:Int){
    this.s = n.toString
  }
}

此类的要点是根据用于实例化该对象的对象的类类型来实例化一个对象及其变量,但是问题是,当调用抽象构造函数时,对象的默认构造函数将扩展抽象对象以某种方式被调用.这会将var的值改回null.

The point of this class is to instantiate an object and its variables depending on the class type of the object used to instantiate it but the problem is that when the abstract constructor is called, the default constructor of object which is extending the abstract object is somehow being called after. This alters the value of var s back to null.

这是我类的一个非常简单的实现,并且我在类B中拥有更多的变量,并且在intMethod和stringMethod中具有更多的逻辑.

This a really simple implementation of my classes and I have more variables in class B and more logic inside intMethod and stringMethod.

我意识到这样做可能是完全错误的方法,因此,如果有更好的方法,请告诉我.

I realize this might be a completely wrong way of doing this, so if there is a better way please let me know.

推荐答案

父类的主体始终在子类的主体之前执行.在您的情况下, A 首先调用 stringMethod intMethod ,然后最后执行 B 的主体,并分配 null s .如果您删除该分配,则它应该可以正常工作:

The body of a super class is always executed before the body of a sub class. In your case A calls stringMethod or intMethod first, then finally B's body is executed, assign null to s. If you remove that assignment, it should work:

abstract class A{
  def this(obj:Object){
    this()
    obj match{
      case s:String => stringMethod(s)
      case n:Int => intMethod(n)
    }
  }

  def stringMethod(s:String)

  def intMethod(n:Int)
}

class B(obj:Object) extends A(obj){
  var s:String = _ // !

  def stringMethod(s:String){
    this.s = s
  }

  def intMethod(n:Int){
    this.s = n.toString
  }
}

val b = new B("foo")
b.s


从没有,风格是有问题的.这里有两种选择:


Neverless, the style is problematic. Here are two alternatives:

trait A {
  def obj: Any
  def s: String
}

class B(val obj: Any) extends A {
  val s = obj match {
    case i: Int    => i.toString
    case x: String => x
    case x         => throw new IllegalArgumentException(x.toString)
  }
}

或者更好地进行静态检查:

Or better statically checked:

object B {
  def apply(i: Int   ): B = new B(i, i.toString)
  def apply(s: String): B = new B(s, s)
}
class B private(val obj: Any, val s: String) extends A

B(1.0) // not allowed

这篇关于如何在Scala中扩展抽象类并使用抽象构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆