spring Kotlin类型在函数参数中提示接口,以接收实现接口的类的任何对象

new9mtju  于 2023-03-22  发布在  Spring
关注(0)|答案(2)|浏览(120)

在Sping Boot 3的Kotlin中,我试图实现一个模式,在控制器中,我将接收一个RequestDto作为@RequestBody,它实现了一个接口DtoInterface,我将把这个dto传递给我的服务。服务的create函数已经TypeHinted了DtoInterface,任何实现这个接口的Dto类都可以传递到那里。
在我当前的实现中,我无法从服务访问dto的属性。

主计长

@RestController
@RequestMapping("api/v1/brands")
class BrandController (private val service: BrandService){
    @PostMapping("/")
    fun postCreate(@RequestBody brandCreateRequestDto: BrandCreateRequestDto): String
    {
        val test = service.create(brandCreateRequestDto);
        return test
    }
}

BrandCreateRequestDto

import com.example.api.dto.DtoInterface

data class BrandCreateRequestDto (
    val name: String,
    val title: String,
    val description: String,
    val slug: String,
    val body: String,
    val status: String,
):DtoInterface

DtoInterface

interface DtoInterface {}

现在从我的BrandService,我想输入hint this DtoInteface来创建一个函数,但是这里的namedata对象中不可用。

品牌服务

@Service
class BrandService (){
    fun create(data: DtoInterface): String {     
        return "Name: " + data.name
    }
}

我在PHP中使用了类似的模式,并且运行得很好。我假设Kotlin中的语法是不同的,但找不到任何类似的解决方案。
短暂性脑缺血

2wnc66cl

2wnc66cl1#

您的DtoInterface没有属性。如果您只知道一个对象实现了DtoInterface,则无法保证该对象具有name属性。
例如,这里有一个类也实现了DtoInterface

data class Square(val sideLength: Int): DtoInterface

必须允许将Square(42)传递给你的服务,因为它实现了DtoInterface。但是在这种情况下,你会看到试图在这个服务上调用data.name将失败。这是我们在编译时就知道的,所以编译器不允许它。
通常使用接口的目的是定义一组可以在子类上保证的公共属性。如果你将name属性添加到DtoInterface,任何子类都必须定义这个属性:

interface DtoInterface {
    val name: String
}

data class BrandCreateRequestDto (
    override val name: String,
    val title: String,
    val description: String,
    val slug: String,
    val body: String,
    val status: String,
) : DtoInterface

有了这些定义,服务可以调用data.name属性,因为我们可以确保所有子类都有这个属性。你可以通过override关键字看到这个属性来自一个超类型。
现在,也许name不应该被认为是你的例子中的公共属性。如果是这样,一个替代方案是简单地将BrandCreateRequestDto声明为你的服务方法的输入,这将解决这个问题:

@Service
class BrandService (){
    fun create(data: BrandCreateRequestDto): String {     
        return "Name: " + data.name
    }
}
qnzebej0

qnzebej02#

除了Joffrey的答案,你还可以使用Kotlin的smart cast feature

@Service
class BrandService (){
    fun create(data: DtoInterface): String {     
        if (data is BrandCreateRequestDto) {
            return "Name: " + data.name
        } else {
            return ""
        }
    }
}

相关问题