Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing classes and interfaces with generic types

I have the following interface that maps and accepts as a parameter a InsectTypesEntity and return a object of a InsectDataModel and another that returns a List<InsectDataModel>

I am trying to do this with generics, as I would like to practice this.

interface InsectInteractorMapper<T> {
    fun map(insectTypesEntity: T): T
    fun map(cursor: Cursor): List<T>
}

Without the generics it would be something like this:

interface InsectInteractorMapper<InsectTypesEntity> {
    fun map(insectTypesEntity: InsectTypesEntity): InsectDataModel
    fun map(cursor: Cursor): List<InsectDataModel>
}

I am trying to get my class that implements this using the generic version of the interface, however, I get many errors related:

1) Return type is 'insectDataModel' which is not a subtype of overridden
public abstract fun map(insectTypesEntity: InsectTypesEntity): InsectTypeEntity defined in InsectInteractorMapper

2) Return type is 'List<InsectDataModel>' which is not a subtype of overridden
public abstract fun map(cursor: Cursor): List<InsectTypesEntity> defined in InsectInteractorMapper

The class that implements the interface

class InsectInteractorMapperImp: InsectInteractorMapper<InsectTypesEntity> {
    override fun map(insectTypesEntity: InsectTypesEntity): InsectDataModel {

        return InsectDataModel(
                insectTypesEntity.friendlyName,
                insectTypesEntity.scientificName,
                insectTypesEntity.classification,
                insectTypesEntity.imageAsset,
                insectTypesEntity.dangerLevel)
    }

    override fun map(cursor: Cursor): List<InsectDataModel> {
        val insectDataModelList: MutableList<InsectDataModel> = mutableListOf()

        cursor.moveToFirst()
        while(cursor.moveToNext()) {
            InsectDataModel().let {
                it.friendlyName = cursor.getString(cursor.getColumnIndexOrThrow(InsectContract.COLUMN_FRIENDLY_NAME))
                it.scientificName = cursor.getString(cursor.getColumnIndexOrThrow(InsectContract.COLUMN_SCIENTIFIC_NAME))
                it.dangerLevel = cursor.getInt(cursor.getColumnIndexOrThrow(InsectContract.COLUMN_DANGER_LEVEL))

                insectDataModelList.add(it)
            }
        }

        cursor.close()
        return insectDataModelList.toList()
    }
}

What would be the best way to get this working correctly with generics?

many thanks for any suggestions,

==== UPDATE Modified interface for in/out variance:

interface InsectInteractorMapper<in E, out M> {
    fun map(insectTypesEntity: E): M
    fun map(cursor: Cursor): List<M>
}

However, I am getting a warning when I try and use the interface:

unchecked assignment java.util.List to java.util.List<InsectDataModel> Reason insectDataModelMapper has raw type so result of map will be erased 

When I use it like this:

insectInteractorMapper = new InsectInteractorMapperImp();
insectDataModelList = insectInteractorMapper.map(cursor);
like image 937
ant2009 Avatar asked Jun 12 '18 16:06

ant2009


People also ask

What is a generic interface in the class library?

The .NET class library defines several generic interfaces for use with the collection classes in the System.Collections.Generic namespace. When an interface is specified as a constraint on a type parameter, only types that implement the interface can be used.

What is a generic interface in typescript?

Summary: in this tutorial, you will learn how to develop TypeScript generic interfaces. Like classes, interfaces also can be generic. A generic interface has generic type parameter list in an angle brackets <> following the name of the interface:

How to create a generic type parameter list for an interface?

A generic interface has generic type parameter list in an angle brackets <> following the name of the interface: interface interfaceName<T> { // ... } Code language: TypeScript (typescript) This make the type parameter T visible to all members of the interface. The type parameter list can have one or multiple types. For example:

How to add constraints to generic interfaces in Java?

You can also add constraints to generic interfaces. Note that the class which will be implementing the generic interface must define the parameter T. To test the above implementation, we will be creating an object from Book with parameter String, and then we will use the add method to add the string value to the Book class.


1 Answers

Since you want a in type and an out type you need to declare those like so:

interface InsectInteractorMapper<in T1, out T2> {
    fun map(insectTypesEntity: T1): T2
    fun map(cursor: Cursor): List<T2>
}

Then your code will work

like image 183
Derek Avatar answered Oct 24 '22 10:10

Derek