The situation is following:
abstract class A {
void doSomething() => print('Do something..');
}
class B implements A {
#override
void doSomething() => print('Do something already..');
}
class C extends A {
}
I have an abstract class A.
Class B implements A. Therefore it overrides doSomething() method. Class C extends A.
Everything works fine, until I'm adding factory constructor to class A:
abstract class A {
factory A() => new B();
void doSomething() => print('Do something..');
}
This leads to an error in my IDE (IntelliJ IDEA):
The generative constructor expected, but factory found
My first idea was to create constructor for class C where I would call factory constructor for A. Is it possible to do?
I got the same problem when I try to extend Exception class. It also has a factory constructor:
abstract class Exception {
factory Exception([var message]) => new _ExceptionImplementation(message);
}
Thats why to create my custom exception I have to implement Exception class instead of extending it and it really confuses me.
I also would like to clarify one terminology question.
Can I say that from point of view of B class, A is an interface, so B is implementing interface A.
However, from point of view of C class, A is an abstract class so C is extending abstract class A. Are these statements correct?
Thank you.
Dmitry.
If a class has no constructor a generative constructor is implicitly added. If a class has an explicit constructor no generative constructor is added.
You have two options.
make the factory constructor a named factory constructor and add a normal constructor
abstract class A {
void doSomething() => print('Do something..');
factory A.name() => new B();
A();
}
or make the normal constructor named and call it explicitly from the extending class
abstract class A {
void doSomething() => print('Do something..');
factory A() => new B();
A.protected();
}
class C extends A {
C() : super.protected();
}
try at DartPad
Your statement is right. If you implement a class it acts as an interface and if you extend it it acts as a base class.
I dont know it works but it solves my problem. And I know there are a lot solution for this may be this solution worst. :) but I want to share with you
Sometimes backend API returns same model but different by values.
like this.
Map<String,dynamic> map1 = {
"version": "2.16.0",
"language_1":"Dart",
"framework_1":"Flutter",
};
Map<String,dynamic> map2 = {
"version" : "10.0.1",
"language_2":"javaScript",
"framework_2":"NodeJs",
};
I need D model so extends other models from D
class D{
D({
this.language,
this.frameWork,
this.version,
});
String? language;
String? frameWork;
String? version;
}
Extends models from D
class A extends D{
A();
factory A.fromJson(Map<String,dynamic> json) => C.fromJsonForA(json);
}
class B extends D{
B();
factory B.fromJson(Map<String,dynamic> json) => C.fromJsonForB(json);
}
And write the factory constructor in other class C
class C extends D implements B,A{
C({
String? language,
String? frameWork,
String? version,
}):super(
language:language,
frameWork:frameWork,
version:version,
);
factory C.fromJsonForB(Map<String,dynamic> json){
final c = C.protected(json);
c.frameWork = json['framework_2'];
c.language = json['language_2'];
return c;
}
factory C.fromJsonForA(Map<String,dynamic> json){
final c = C.protected(json);
c.frameWork = json['framework_1'];
c.language = json['language_1'];
return c;
}
factory C.protected(Map<String,dynamic> json){
return C(
version: json["version"],
);
}
}
And I used :)
A modelA = A.fromJson(map1);
B modelB = B.fromJson(map2);
class Example {
Example._();
static printModel(D model){
print("${model.language} : ${model.frameWork} version : ${model.version}");
}
}
Related
I have a class that has a mixin generated through freezed.
I have another class that has a mixin generated through freezed.
I want to extend the second class, but I receive a type error because the mixin methods have differences.
Example:
class A with _$A {
const factory A.initial() = _Initial;
}
class B with _$B {
const factory B.final() = _Final;
}
I want:
class B extends A with _$B, _$A {
const factory B.final() = _Final;
}
and then I should be able to use:
B.initial()
Why I can't assign Future<T> fut = Future.value(Student()) where as Future<User> fut = Future.value(Student()) is possible.
void main() {}
class Test<T extends User> { // <----- T extends User (which is base class for Student & Teacher)
Future<T> fut = Future.value(Student()); // <----- Compiler error
Future<User> fut2 = Future.value(Student()); // <----- works fine
}
class User {}
class Teacher extends User {}
class Student extends User {}
There is not necessarily any relationship between T and Student. You've only established that T and Student both derive from User. For example, T could be Teacher; how would you assign a Future<Student> to a Future<Teacher>?
I am adapting my code to clean architecture (following the brilliant tutorial from Reso Coder) and have an issue now with the toJson method on a nested structure. The difference is that the data model class is extended from the data entity class, compared to my previous code.
I found the exactly same issue here, however, I wonder if there is a better/cleaner solution?!
class MyData extends Equatable{
final List<MyNestedData> nested;
MyData(this.nested);
}
class MyNestedData extends Equatable {
final int x;
final int y;
MyNestedData({this.x, this.y});
}
class MyDataModel extends MyData{
final List<MyNestedData> nested;
MyDataModel(List<MyNestedDataModel> nested) : super (nested);
Map<String, dynamic> toJson() => {
"nested": List<dynamic>.from(nested.map((x) => x.toJson())),
};
}
class MyNestedDataModel extends MyNestedData {
MyNestedData({x, y}) : super (x: x, y: y);
Map<String, dynamic> toJson() => {
x: x,
y: y
}
}
MyDataModel obviously ignores the adapted parameter definition List<MyNestedDataModel> nested and uses List<MyNestedData> of the parent instead. So how would I then approach the toJson method within MyNestedDataModel instead?
I would like to write a Scala test which checks the exact class of an object created with factory method.
class Base { }
class Derived extends Base { }
class TestSpec {
test("test instance class") {
val result = new Derived()
// I want to check that result is exactly Derived type
result should be a[Derived]
result should not be a[Base]
}
}
I'm looking for something to test if object returned from my factory method for specific parameters is always base class. So it would be something like this is C#:
public class Base { }
public class Derived : Base { }
public class Program
{
public static void Main(string[] args)
{
var baseObject = new Base();
var derivedObject = new Derived();
var baseResult = baseObject.GetType().IsSubclassOf(typeof(Base));
var derivedResult = derivedObject.GetType().IsSubclassOf(typeof(Base));
Console.WriteLine(string.Format("Base is subclass of Base: {0}\nDerived is subclass of Base: {1}", baseResult, derivedResult));
}
}
you can do this :
class A{}
class B extends A{}
val result = new B()
result.getClass.getName shouldEqual classOf[B].getName
result.getClass.getName.equals(classOf[A].getName) shouldBe false
new Derived() will always be an instance of Base as it inherits from Base, which means:
new Derived().isInstanceOf[Base]
will return true.
But the opposite is false: Base won't be an instance of Derived.
Thus, to check if it's the Base class (and not the Derived class), you can use these two combined conditions:
new Base() should not be a[Derived]
new Base() shouldBe a[Base]
and to check if it's the Derived class, the following is enough:
new Derived() shouldBe a[Derived]
You can call an auxiliary constructor in the base class via the derived class primary constructor:
class Base(n:Int) {
def this(n:Int, i:Int) = {
this(n)
println(i)
}
}
class Derived(n:Int, i:Int) extends Base(n, i)
Is there a syntax for calling an auxiliary base-class constructor from an auxiliary derived-class constructor? This doesn't work:
class Derived2(n:Int) extends Base(n) {
def this(n:Int, i:Int) = {
super.this(n, i) // Can't do this
println(i)
}
}
In other languages, you can do this, but you must call the base-class constructor first, which is why I tried to do it here.
Note that I am looking for the syntax for the call rather than alternative ways to achieve the same result.
In Scala you have to go through the default constructor no matter what, which forces you to choose one super construction in your class instantiation. This is basically what you're trying to do in terms of java:
public class Derived2 extends Base {
public Derived2(int n, int i) {
super(n, i);
}
public Derived2(int n) {
super(n);
}
}
Since in Scala you have to go through the default constructor this is what's happening:
public class Derived2 extends Base {
public Derived2(int n, int i) {
this(n);
super(n, i); //does not compile
}
public Derived2(int n) {
super(n);
}
}
So, as is normal in Java, you can only call super or this as the first line of your constructor implementation. Since Scala forces the call to the default constructor, there's no way around only using one implementation of the Base constructor.
There is no work around, as this isn't really dogmatic Scala. I would suggest changing your design here. Inheritance in Scala is usually done through traits, not classes or abstract classes.
Here's what an alternative might look like using a trait:
trait Base2 {
val a:Int
}
class Derived3(n: Int) extends Base2 {
val a = n
def this(n: Int, i: Int) = {
this(n)
}
}