How to extra generic parameter after where statement? - oop

I have an abstract class as follow:
class BaseReturnType { }
class DerivedReturnType : BaseReturnType { }
abstract class BaseClass<T> where T : BaseReturnType
{
public abstract T PolymorphicMethod();
}
class DerivedClass : BaseClass<DerivedReturnType>
{
public override DerivedReturnType PolymorphicMethod()
{
return new DerivedReturnType();
}
}
So if add exta parrameter for Generic called T2 how do I put extrac constraining on this?
abstract class BaseClass<T, **T2**> where T : BaseReturnType ???
{
public abstract T PolymorphicMethod();
}

abstract class BaseClass<T, **T2**> where T : BaseReturnType where T2 : BaseTypeForT2
{
public abstract T PolymorphicMethod();
}
as per here.

Related

How to initialize a variable of an abstract class from a child class

I have an abstract class:
inner abstract class Base {
fun Buscar(): Int {
// Do something with a object called Q
}
}
And two secondary class that I need to initialize Q with certain class
inner class BFS(): Base() {
constructor(): this() {
Q = Cola()
}
}
inner class DFS(): Base() {
constructor(): this() {
Q = Pila()
}
}
How can I do that?
--- EDIT ---
Pila() and Cola() are classes from an abstract class called Secuencia:
abstract class Secuencia<T> { ... }
public class Pila<T> : Secuencia<T>() { ... }
public class Cola<T> : Secuencia<T>() { ... }
You just need to make Q abstract and initialise it in your class, e.g.
sealed class Algo(val message: String)
class Cola : Algo("cola")
class Pila : Algo("pila")
abstract class Base {
// all concrete classes need to define a value for 'q'
abstract val q: Algo
fun buscar(): Int {
// you can reference q here since a concrete class will have initialised it
println(q.message)
return 1
}
}
class BFS(): Base() {
// since q is abstract it needs to be overridden in a concrete class
override val q = Cola()
}
class DFS(): Base() {
override val q = Pila()
}
fun main() {
BFS().buscar()
DFS().buscar()
}
>> cola
>> pila

Map abstract type in Kotlin with MapStruct

I'm trying to map an abstract class with Mapstruct in Kotlin, but getting the following error:
AnimalMapper.java: error: The return type AnimalOutput is an abstract class or interface. Provide a non abstract / non interface result type or a factory method.
My implementation:
#Mapper(componentModel = "jsr330")
interface AnimalMapper {
fun mapToDogOutput(dogInput: DogInput): DogOutput
fun mapToCatOutput(catInput: CatInput): CatOutput
fun mapToAnimalOutput(animalInput: AnimalInput): AnimalOutput {
when (animalInput) {
is DogInput -> mapToDogOutput(animalInput)
is CatInput -> mapToCatOutput(animalInput)
}
throw RuntimeException("Unsupported animal type");
}
}
sealed class AnimalInput {
abstract val name: String
}
data class CatInput(
override val name: String,
val catProperty: Int,
) : AnimalInput()
data class DogInput(
override val name: String,
val dogProperty: Float,
) : AnimalInput()
sealed class AnimalOutput {
abstract val name: String
}
data class CatOutput(
override val name: String,
val catProperty: Int,
) : AnimalOutput()
data class DogOutput(
override val name: String,
val dogProperty: Float,
) : AnimalOutput()
In my old java project, this corresponding implementation works as expected:
#Mapper(componentModel = "jsr330")
interface AnimalMapper {
DogOutput mapToDogOutput(DogInput dogInput);
CatOutput mapToCatOutput(CatInput catInput);
default AnimalOutput mapToAnimalOutput(AnimalInput animalInput) {
if (animalInput instanceof DogInput) {
return mapToDogOutput((DogInput) animalInput);
}
if (animalInput instanceof CatInput) {
return mapToCatOutput((CatInput) animalInput);
}
throw new RuntimeException("Unsupported animal type");
}
}
public abstract class AnimalInput {
public String name;
}
public abstract class CatInput extends AnimalInput {
public String name;
public int catProperty;
}
public abstract class DogInput extends AnimalInput {
public String name;
public float dogProperty;
}
public abstract class AnimalOutput {
public String name;
}
public abstract class CatOutput extends AnimalOutput {
public String name;
public int catProperty;
}
public abstract class DogOutput extends AnimalOutput {
public String name;
public float dogProperty;
}
I'm using the following dependency versions:
mapstructVersion: 1.4.2.Final
kotlinVersion: 1.5.21 (jvmTarget 16)
Anyone have an idea, how to fix this issue in my Kotlin project?
The reason why this is not working in Kotlin is due to the fact that the generated code by Kotlin marks the mapToAnimalOutput method as an abstract method.
You'll need to use #JvmDefault on that method in order for Kotlin to generate the correct modifiers for the method.

Is it ok to override a virtual method but provide no implementation?

I'm trying to create a class heirachy for a game, there is an Item class which is the base class for all items in the game. The problem is that some derived items (like potion) might not implement some of the abstract methods defined by the item.
Is it ok for derived classes to implement an abstract method with "do nothing"?
Example: https://dotnetfiddle.net/jJABN1
using System;
using System.Collections.Generic;
public abstract class Item
{
public abstract void Use();
}
public class Potion : Item
{
public override void Use()
{
// do nothing
return;
}
}
public class Sword : Item
{
public override void Use()
{
Console.WriteLine("Sword used!");
return;
}
}
public class Program
{
public static void Main()
{
List<Item> items = new List<Item>();
Item potion = new Potion();
Item sword = new Sword();
items.Add(potion);
items.Add(sword);
for (int i = 0; i < items.Count; i++)
{
Item item = items[i];
item.Use();
}
}
}
One of Robert Martin's SOLID Principles - Interface Segregation Principle addresses this situation. It basically says that a client should not be exposed to methods it doesn't need.
An example of violating the Interface Segregation Principle:
// Abstraction
public abstract class Printer
{
public abstract void Print();
public abstract void Scan();
}
// Implementations
public class SomeAllInOnePrinter : Printer
{
public override void Print()
{
Console.WriteLine("Printing...");
}
public override void Scan()
{
Console.WriteLine("Scanning...");
}
}
public class SomeBasicPrinter : Printer
{
public override void Print()
{
Console.WriteLine("Printing...");
}
public override void Scan()
{
// Basic printers can't scan
}
}
This is usually solved by separating an abstract class to multiple smaller abstract classes that can optionally inherit one other:
// Abstractions
public abstract class Printer
{
public abstract void Print();
}
public abstract class AllInOnePrinter : Printer
{
public abstract void Scan();
}
// Implementations
public class SomeAllInOnePrinter : AllInOnePrinter
{
public override void Print()
{
Console.WriteLine("Printing...");
}
public override void Scan()
{
Console.WriteLine("Scanning...");
}
}
public class SomeBasicPrinter : Printer
{
public override void Print()
{
Console.WriteLine("Printing...");
}
}
Technically, there could be an edge-case (should be uncommon!) where a deriving class doesn't need to implement all the methods, in such a case I'd rather it to override and throw an error to signal the user that this method should not be used.
That said, in the provided example there is only one method, so the question is: if a derived class doesn't need this method - why do you need to inherit the abstract class to begin with? if it's just in order to provide an example that's understandable - but better improve the example to include other methods that are used in the derived class.

override function with concrete type parameter

Hi I would like know why the following example doesn't work
abstract class BaseClass {
}
class ConcretClasOne : BaseCalculator {
}
class ConcretClasTwo : BaseCalculator {
}
abstract class BaseRun {
abstract fun run(param: BaseClass): Int
}
class ConcretRun : BaseRun {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
this shows me a message run overrides nothing.
I suppose that kotlin isn't able to match the abstract class and the concrete implementation, but what other alternative is there to emulate this behavior, that the run method in the concrete class ConcretRun should receive a concrete param ConcretClasOne?
Generics
Using generics, you can make the base class have a type extending the base class, so that the run method can take that type in.
abstract class BaseClass {
}
class ConcretClasOne: BaseCalculator {
}
class ConcretClasTwo: BaseCalculator {
}
abstract class BaseRun<T: BaseClass> {
abstract fun run(param: T): Int
}
class ConcretRun: BaseRun<ConcretClasOne> {
override fun run(param: ConcretClasOne): Int {
return 0
}
}
Why your code doesn't work
At the moment you are trying to override a method with a more specific type, but as the more general base method can accept more types the more specific method cannot override it.

how can I do if many class inherit one interface with Ninject.Extensions.Conventions

In my item,there are multi class inherit one interface, and many interface like this.
for example,class A|B|C inherit interface Ilog, class F|E|G inherit interface IData, and class H|I|J inherit IBase, and so on. now ,I want bind All Interface use Ninject.Extensions.Conventions,how can I do. if use conventions can't do it,please tell me the best way to do it. and I want somebody tell me how use Ninject.Extensions.Conventions in Item,don't tell me the concrete syntex,I want to know how to organize my class and Interface let bind interface easier,Thank you for your help!
code example like this:
public interface Ilog
{
//... ...
}
public class A:IIlog
{
//... ...
}
public class B:ILog
{
//... ...
}
public class C:ILog
{
//... ...
}
public interface IData
{
//... ...
}
public class H:IData
{
//... ...
}
public class E:IData
{
//... ...
}
public class G:IData
{
//... ...
}
public interface IBase
{
//... ...
}
public class H:IBase
{
//... ...
}
public class I:IBase
{
//... ...
}
public class J:IBase
{
//... ...
}
now,I want resolve interface Ilog to A,IData to E,IBase to H,how can I Do with Ninject.Extensions.Conventions? if many interface like this,how can I do?