Home > front end >  How to create a generic class of generics in dart?
How to create a generic class of generics in dart?

Time:12-19

I am trying to create a class "CombinedResource" that will contain 2 properties, each is of the type "Resource".

Now the Resource class is as follows:

class Resource<T>{
  final T? data;
  Resource({this.data});
}

And the CombinedResource class is as follows:

class CombinedResource<T1 extends Resource<Ta>, T2 extends Resource<Tb>, Ta, Tb>
 {
  final T1? resourceA;
  final T2? resourceB;
  
  const CombinedResource._({
    this.resourceA,
    this.resourceB,
  });

  factory CombinedResource.create(
    Resource<Ta> rA,
    Resource<Tb> rB,
  ) =>
      CombinedResource._(
        resourceA: rA,
        resourceB: rB,
      );
}

Now, the problem is that the compiler is giving me an error on the factory method:

The argument type 'Resource<Ta>' can't be assigned to the parameter type 'T1?'.

I tried changing the CombinedResource class to be as follows:

class CombinedResource<Ta,Tb>
{
  final Resource<Ta>? resourceA;
  final Resource<Tb>? resourceB;
  
  const CombinedResource._({
    this.resourceA,
    this.resourceB,
  });

  factory CombinedResource.create(
    Resource<Ta> rA,
    Resource<Tb> rB,
  ) =>
      CombinedResource._(
        resourceA: rA,
        resourceB: rB,
      );
}

This caused another problem, where I was unable to create an instance of CombinedResource:

 CombinedResource.create(
                  Resource(data:"sdc"), Resource(data:"sdc"));

  The argument type 'String' can't be assigned to the parameter type 'Resource<String>?'.

What am I doing wrong here?

Update: The second approach is working fine.

CodePudding user response:

Your first attempt failed because you do:

  factory CombinedResource.create(
    Resource<Ta> rA,
    Resource<Tb> rB,
  ) =>
      CombinedResource._(
        resourceA: rA,
        resourceB: rB,
      );

but CombinedResource._ expects arguments of type T1 and T2. You've specified that T1 is derived from Resource<Ta>, which means that an instance of a T1 must be an instance of a Resource<Ta>. The reverse, however, is not true: not every Resource<Ta> is necessarily a T1. Therefore a Resource<Ta> is not implicitly assignable to a T1. (Downcasts are potentially unsafe.)

I don't know why you inexplicably made your factory constructor use a different signature from your private constructor, but it'd work if you fixed it to use matching types:

  factory CombinedResource.create(
    T1 rA,
    T2 rB,
  ) =>
      CombinedResource._(
        resourceA: rA,
        resourceB: rB,
      );
  • Related