如何在 Kotlin 中用继承的类覆盖方法?

     2023-02-22     26

关键词:

【中文标题】如何在 Kotlin 中用继承的类覆盖方法?【英文标题】:How to override method with inherited class in Kotlin? 【发布时间】:2022-01-12 09:16:14 【问题描述】:

我正在探索并积极在 Kotlin 的生产环境中使用泛型。

Kotlin + 泛型对我来说是一个很大的难题,所以也许你可以解释一下并帮助我理解它与 Java 相比是如何工作的。

我有课 AbstracApiClient(不是很抽象)

class AbstracApiClient 
  
  open protected fun makeRequest(requestBuilder: AbstractRequestBuilder) 
    // ... 
  

AbstractRequestBuilder(不是很抽象):

open class AbstractRequestBuilder 
  ...

ConcreteApiClient 继承 AbstractApiClient 应该用从 AbstractRequestBuilder 继承的 ConcreteRequestBuilder 覆盖 makeRequest:

class ConcreteApiClient: AbstractApiClient() 
  
  protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) 
    // ... 
  


class ConcreteRequestBuilder: AbstractRequestBuilder()

因为我会有更具体的 API 客户端。我想做一个抽象,我可以传递继承的具体请求构建器并覆盖`make requests 方法。

    我尝试按原样使用它,但不起作用 我尝试了这个符号protected open fun <R: ApiRequestBuilder> make request(request builder: R),但它与我想要的覆盖函数不匹配:protected override fun make request(request builder: ConcreteRequestBuilder)

我还有什么其他选择?我在这里遗漏了什么吗?

注意:在这种情况下我不能使用interfaceabstract classes,所以理想情况下我想找到一种继承和函数覆盖的方法。

【问题讨论】:

您能否再解释一下在没有泛型的情况下,目前的方法有什么不适用的?你得到什么错误/使用哪个代码? 覆盖方法在这两种情况下都不起作用,因此方法protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) 无法与我使用的两种指定方法中的任何一种匹配。 啊,是的,我明白了。我将尝试在答案中解释 【参考方案1】:

你不能用更具体的参数类型覆盖一个方法,因为它会破坏Liskov's substitution principle:

val client: AbstractApiClient = ConcreteApiClient()

client.makeRequest(AbstractRequestBuilder())

正如您在上面看到的,ConreteApiClient 实现必须能够处理父类的所有可能输入,因为它可以通过父类的 API 访问。

要做你想做的事,你需要通过泛型来限制父类本身:

open class AbstractApiClient<R : AbstractRequestBuilder> 
  
  open protected fun makeRequest(requestBuilder: R) 
    // ... 
  


class ConcreteApiClient: AbstractApiClient<ConcreteRequestBuilder>() 
  
  protected override fun makeRequest(requestBuilder: ConcreteRequestBuilder) 
    // ... 
  

这样,AbstractApiClient&lt;R&gt; 的任何实例都必须显示它接受的请求构建器类型(在类型参数中)。它防止了上述问题,因为现在父类型也携带信息:

// doesn't compile
val client: AbstractApiClient<AbstractRequestBuilder> = ConcreteApiClient() 

// this compiles
val client: AbstractApiClient<ConcreteRequestBuilder> = ConcreteApiClient()

我尝试了这种表示法保护的开放乐趣 发出请求(请求生成器:R)

现在关于这个尝试,它不起作用,因为如果你使 method 通用(而不是 class),这意味着方法的每个实现都必须处理 所有种R(不是每个实现一个R)。将泛型放在类上允许为类的每个实例指定一次泛型参数。

【讨论】:

谢谢,我尝试了类似的方法,但我认为中途停止了。我是否正确地认为它在 Java 中是允许的,所以允许 Java 打破 Liskov 的原则? @DmytroChasovskyi Java 也不允许使用更具体的参数类型覆盖方法。如果您尝试使用 @Override 注释该方法,则它不应编译。 然而,Java 在泛型方面确实打破了这些方面的一些事情,因为它允许raw types。因为这个原因,Java 的泛型被破坏了

Python:装饰一个在继承时打算被覆盖的类方法

】Python:装饰一个在继承时打算被覆盖的类方法【英文标题】:Python:Decoratingaclassmethodthatisintendedtobeoverwrittenwheninherited【发布时间】:2013-09-2210:01:19【问题描述】:假设我有一些基类:classTask:defrun(self):#overridethis!现在,我希望其... 查看详情

如何在继承的类上使用 python 模块

】如何在继承的类上使用python模块【英文标题】:Howtouseapythonmoduleoninheritedclass【发布时间】:2021-05-1419:39:01【问题描述】:我在base.py中有一个基类A:importmodule1classA:deftest(self):module1.sample("test")然后在new.py中创建了一个新类B,它... 查看详情

kotlin中级---kotlin类之的继承.md

Kotlin继承类1.超类(Any)在Kotlin中,所有的类都是继承自Any类,这是一个没有父类型的类。即当我们定义各类时,它默认是继承于Any类的例如:classPerson因为Any这个类只是给我们提供了equals、hashcode、toString三个方法&#x... 查看详情

继承和抽象方法

...在的类,必须是抽象类才行,在Class之前写上abstract即可如何使用抽象类和抽象方法1、不能直接创建new抽象类对象2.必须用一个子类来继承抽象父类3,子类必须覆盖重写抽象父类当中的所有抽象方法覆盖重写(实现):去电抽象... 查看详情

从继承的类中覆盖虚拟方法但保留基类的注释[重复]

】从继承的类中覆盖虚拟方法但保留基类的注释[重复]【英文标题】:Overridingavirtualmethodfromwithinaninheritedclassbutkeepthecommentsofthebaseclass[duplicate]【发布时间】:2012-11-2519:47:09【问题描述】:可能重复:CommentInheritanceforC#(actuallyanylangu... 查看详情

es6中的类和对象继承(代码片段)

...对象是由属性和方法组成的:属性:事物的特征,在对象中用属性来表示(常用名词)方法:事物的行为,在对象中用方法来表示(常用动词)1.2类class类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,通过... 查看详情

没有直接继承的覆盖方法实现注入

】没有直接继承的覆盖方法实现注入【英文标题】:Overridingmethodimplementationinjectionwithoutdirectinheritance【发布时间】:2018-10-2609:48:46【问题描述】:你们知道是否有可能将不继承任何东西的类A的方法的实现注入到从类B继承的类C中... 查看详情

在继承的类中覆盖 NSLayoutConstraint

】在继承的类中覆盖NSLayoutConstraint【英文标题】:OverridingNSLayoutConstraintinaninheritedclass【发布时间】:2018-06-1816:13:55【问题描述】:我的代码中有两个类,一个是NameCell,它包含一个带有文本的简单UILabel。第二个是NameValueCell,它... 查看详情

如何覆盖模块中的类常量和方法?

】如何覆盖模块中的类常量和方法?【英文标题】:Howtooverrideclassconstantsandmethodsfromamodule?【发布时间】:2022-01-2403:31:33【问题描述】:我正在尝试创建一个模块来为某些类定义一些方法和常量。这意味着可以在模块和包含该模... 查看详情

2016710101452016-2017《java程序设计》java的继承中什么叫方法覆盖,是如何实现的?

方法覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而在实现时,就需要实现接口声明的所有方法。除了这个典... 查看详情

如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?

】如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?【英文标题】:HowtoimplementtheoverridemethodsofEqualsandGetHashCodeinaclassthatimplementsIProxyGenerationHookinCastle.Core?【发布时间】:2021-04-1817:06:39【问题描述】:阅... 查看详情

无法在 ADO .NET 实体模型 edmx 中的类继承中执行覆盖

】无法在ADO.NET实体模型edmx中的类继承中执行覆盖【英文标题】:cannotperformoverrideinclassinheritanceinADO.NETEntityModeledmx【发布时间】:2022-01-1702:35:02【问题描述】:我必须构建一个访问现有数据库表的.netWeb应用程序。数据库为不同的... 查看详情

在andriodstudio中用kotlin代码如何实现不同页面的参数传递

参考技术A先用AndroidStudio来创建你的第一个Kotlin应,虫母护甲低,但是有高回复,搭配沉思者和治疗可以做三号位前排,反而是治疗,作为和王者蔡文姬一样的存在,本身并不肉,只是一个脆皮。 查看详情

kotlin类的继承①(使用open关键字开启类的继承|使用open关键字开启方法重写)(代码片段)

...open关键字开启方法重写一、使用open关键字开启类的继承Kotlin中的类默认都是封闭的,无法被继承,如果要想类被继承,需要在定义类时使用open关键字;定义一个普通的Kotlin类:classPerson(valname:String,valage:Int)funinfo()println("name:$name,age:$... 查看详情

kotlin类的继承①(使用open关键字开启类的继承|使用open关键字开启方法重写)(代码片段)

...open关键字开启方法重写一、使用open关键字开启类的继承Kotlin中的类默认都是封闭的,无法被继承,如果要想类被继承,需要在定义类时使用open关键字;定义一个普通的Kotlin类:classPerson(valname:String,valage:Int)funinfo()println("name:$name,age:$... 查看详情

在 Kotlin lambda 表达式中覆盖多个接口方法

】在Kotlinlambda表达式中覆盖多个接口方法【英文标题】:OverridingmultipleinterfacemethodsinKotlinlambdaexpressions【发布时间】:2018-03-1401:52:01【问题描述】:假设我有一个Callbacks接口,有两个方法onCurrentLocation和onError:publicinterfaceCallbacksv... 查看详情

如何在不复制整个方法的情况下将装饰器添加到 Python 中的继承方法?

】如何在不复制整个方法的情况下将装饰器添加到Python中的继承方法?【英文标题】:HowtoaddadecoratortoinheritedmethodinPythonwithoutcopyingwholemethod?【发布时间】:2015-07-1022:19:59【问题描述】:我有一个从其父类继承修饰属性的类。我想... 查看详情

如何在伴随对象中覆盖 kotlin 接口

】如何在伴随对象中覆盖kotlin接口【英文标题】:Howtooverridekotlininterfaceinsidecompanionobject【发布时间】:2021-12-1522:13:43【问题描述】:我正在使用--libraryjvm-retrofit2和coroutines=true生成带有open-apicodegen的代码。我正在编写一个使用REST... 查看详情