I want to define a constructor in an abstract class that will create specific subclasses.
abstract class A { type Impl <: A def construct() : Impl = { val res = new Impl() //compile error: class type required but A.this.Impl found // do more initialization with res } } class B extends A {type Impl = B} class C extends A {type Impl = C} //... val b = new B b.construct() // this should create a new instance of B
What is wrong here? Can this be implemented? The EDIT: . Explanation: I want to abstract using the construction method. I do not want to cause separate new Band new Csubclasses or associated facilities.
new B
new C
You need to explicitly call the constructor if you want to create a new instance.
abstract class A { def newInstance(): this.type; def construct() : this.type = { val res = newInstance() } } class B extends A { def newInstance() = new B() }
Scala erases the type at runtime, so there is no way to find out what Impl meant when creating the class.
You put the constructor in a companion object, not in an abstract class. Like this:
object A { def apply(i:Int):A = new B(...) def apply(s:String):A = new C(...) }
A, , , A(42) A("foobar"). - , , . , . - , apply.
A
A(42)
A("foobar")
apply
. - , , , . -, , .
def newInstance[T:ClassManifest]:T = { val klass = implicitly[ClassManifest[T]].erasure val constr = klass.getConstructors()(0) constr.newInstance().asInstanceOf[T] } abstract class A { def construct(implicit cm:ClassManifest[this.type]): this.type = { val res = newInstance[this.type] res } } class B extends A
, . Scala (Oderski, Spoon, Venners) . . " ", . " ".
:
abstract class A($params) { // do common initialisation here def construct() : A def foo(...) = { ... val bar = construct() ... } } class B($moreparams) extends A($someparams) { // do special initialisation here def construct() = new B() }
, , . , ) , ) (, , , ).
, construct A. .
construct
Following my comment, I remained in the answer Monkey. One way to solve this problem is to use the Curiously Recurring Template Pattern (CRTP) along with self types:
Monkey
abstract class A[T <: A[T]] { this: T => def newInstance(): T; def construct(): T = { val res = newInstance() res } def some(): T = this } class B extends A[B] { def newInstance() = new B() }
There may be a better solution, but so far I have found.
Source: https://habr.com/ru/post/1788908/More articles:jquery scrolltop and scrollleft work fine, but on iphone do they all scroll another bar to its home position? - javascriptProblems with iPad / jQuery.animate (scroll) - jqueryIs there a library in objective-c or c that will do OCR? - objective-cAndroid: SQLite Query not binding integer parameters? - androidCan I add an interval every 4 characters in vi? - viI need a list of all my PHP classes and the files they are in - can I do this in the Netbeans IDE? - phpRails: Can't use the methods defined in the application helper as part of email presentation development? - ruby-on-railshttps://translate.googleusercontent.com/translate_c?depth=1&pto=aue&rurl=translate.google.com&sl=ru&sp=nmt4&tl=en&u=https://fooobar.com/questions/1788911/how-to-copy-a-structure-with-pointers-to-data-inside-so-to-copy-pointers-and-data-they-point-to&usg=ALkJrhj1M_JdiXKCIZZYPCDhTYAePoAqewWhich column matches? - phpWhy does he say that "push_back" has not been declared? - c ++All Articles