首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

当方法没有被重写时,为什么要使用“协变”?

当方法没有被重写时,使用"协变"的原因是为了实现方法的返回值类型的灵活性和扩展性。协变是指在派生类中的方法重写时,可以将返回值的类型设定为基类中对应方法返回值的子类。通过使用协变,我们可以在基类中定义一个通用的方法,并在派生类中根据具体需求返回更具体的子类类型。

使用协变的好处包括:

  1. 灵活性:使用协变可以在派生类中返回更具体的子类类型,从而使得方法的返回值更灵活。这样,在调用该方法时,可以根据实际需要接收更具体的子类对象,而不需要进行强制类型转换。
  2. 扩展性:通过协变,可以在不影响基类的情况下,在派生类中扩展方法的返回值类型。这样,在基类已经编写好并广泛使用的情况下,可以通过派生类来增加更多的返回值类型,以满足更多的应用场景。

应用场景:

协变广泛应用于对象的多态性,特别在面向对象的编程中常见。它可以提高代码的可维护性和可扩展性,尤其在需要处理多个相关类型的情况下,通过协变可以减少重复的代码,并且提供更灵活的接口。

举例来说,假设我们有一个基类Animal,其中定义了一个方法GetSound(),返回一个声音的对象,然后有派生类Cat和Dog,它们分别重写了GetSound()方法,返回具体的CatSound和DogSound对象。如果我们在基类Animal的方法声明中使用了协变,那么在调用GetSound()方法时,可以根据具体的派生类来获取对应的声音对象,而无需进行类型转换。

腾讯云相关产品:

对于云计算领域,腾讯云提供了一系列的产品和服务,以下是一些推荐的产品和产品介绍链接地址,可以根据具体需求选择适合的产品:

  1. 云服务器 CVM:提供高性能、安全可靠的云服务器实例,满足各类业务场景的需求。链接:https://cloud.tencent.com/product/cvm
  2. 云数据库 MySQL:基于腾讯云的高性能、可扩展的关系型数据库,适用于各类在线应用场景。链接:https://cloud.tencent.com/product/cdb_mysql
  3. 腾讯云容器服务 TKE:基于 Kubernetes 的高性能容器管理服务,提供一站式的容器部署、管理和运维能力。链接:https://cloud.tencent.com/product/tke
  4. 腾讯云人工智能 AI:腾讯云提供多种人工智能服务,包括自然语言处理、图像识别、智能语音等,满足不同场景下的需求。链接:https://cloud.tencent.com/product/ai

以上是腾讯云的一些相关产品和服务,可以根据具体需求进一步了解和选择合适的产品。

相关搜索:当被调用的方法没有返回时,取消整个任务为什么当更新被调用(Pygame Pong)时,球没有移动?当使用Telethon for Telegram时,如何纠正“‘协程’对象没有属性‘数据’”错误?当类被添加到元素中时,为什么我的CSS没有被应用?在C++中使用成员函数的向量时,有没有办法实现协变返回类型?为什么当父节点甚至没有被更新时,子节点会被重新渲染?当类型被擦除时,隐式查找要通过泛型调用的正确方法是什么?当从选择框中选择一个项目时,为什么component类中的方法没有被调用?当reflect.Value被传递给golang中的接口时,为什么不能使用Pointer()方法?当使用ets()时,为什么R没有响应并崩溃?当href被点击时,有没有更好的方法来防止整个页面滚动?为什么我的处理程序方法在定义为lambda时没有被触发?当AutoGenerateColumns ="True"使用DataGrid时,为什么DataAnnotations <Display(Name:="My Name")>被忽略当使用导航器时,我如何解析方法'ancestorStateOfType‘在null上被调用?当没有<options>类型的标记被编码时,如何使用selenium点击DIV下拉值当字符串没有被特定字符包围时,使用空格拆分字符串当一个用户表单被卸载时,为什么相关的对象没有被设置为空?当没有设置responseType参数时,为什么下面被覆盖的方法返回Promise<HTTPResponse<Buffer>>?当一个链接被点击时,除了使用的方法'scroll top‘之外,还有什么替代方法吗?当更多的内存分配完成时,为什么程序使用的内存没有改变?
相关搜索:
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C#高级语法之泛型、泛型约束,类型安全、逆和协(思想原理)

一、为什么使用泛型?...:泛型无法作为参数、逆泛型无法作为返回值。...逆: ? : ? 语法都是一些 非常粗糙的东西,重要的是思想、思想、思想。然后我们来看一下为什么要有逆和协? 什么叫做类型安全?...所以逆变作为参数传递,类型是安全的。 思考:那么,现在你能明白上面那个错误,为什么泛型无法作为参数、逆泛型无法作为返回值”了吗?...,但是实际上返回的类型是Animal //所以就存在Animal类型转换为Dog类型,所以就有可能失败 //所以逆泛型无法作为返回值 T In(); void AddAnimal

6.9K30

编码最佳实践——里氏替换原则

(与代码中能替换的类型有关) 子类型的方法参数必须是支持逆的 子类型的返回类型必须是支持的 子类型不能引发不属于已有异常层次结构中的新异常 契约 我们经常会说,面向接口编程或面向契约编程。...1.子类型不能加强前置条件 子类重写包含前置条件的超类方法,绝不应该加强现有的前置条件,这样做会影响到那些已经假设超类为所有方法定义了最严格的前置条件契约的客户端代码。...方法需要ICovariant的实例,完全可以使用ICovariant的实例替代之。...因为不使用泛型类型,C#方法的返回类型就不是的。换句话说,这种情况下(普通类)的继承是不具备能力的。...C#语言的方法参数类型和返回类型都是不可变的,只有在设计泛型才能将类型定义为可的或可逆的。

1.3K20
  • 方法重载与重写

    重写重写发生在子类与父类之间,子类重新定义了父类的方法重写要求子类按照父类重写方法有相同的方法名、参数列表和返回类型。 不能存在同一个类中,在继承或实现关系的类中。 方法重载又可称为什么?...如果我们更改重载方法的返回类型,则将导致模棱两可的行为。 客户将如何知道哪种方法将返回哪种类型。 由于这种不同,重载方法中不允许使用不同的返回类型。 是否可以在Java中重载main()方法?...Java不允许覆盖静态方法。 如果在子类中创建一个具有相同名称的静态方法,则它是一个新方法,而不是覆盖的方法为什么Java不允许重写静态方法重写方法,您需要一个类的实例。...方法覆盖发生在两个具有层次关系的类中。 3.方法重载中的参数必须不同。 方法覆盖中的参数必须相同。 4.方法重载是一个编译概念。 方法重写是运行时概念。 Java中的返回类型是什么意思?...方法返回类型是一种在子类中重写方法可以用“更窄”类型替换的方法。 假设类B是类A的子类。类A和类B中都有一个get()方法

    1.2K21

    C++-带你走进多态(1)

    举个栗子:比如买票这个行为,普通人买票,是全价买票;学生买票,是半价买票;军人买票是优先买票。 2....调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写  BuyTicker就是虚函数,构成多态就必须完成虚函数的重写,而且必须通过基类的指针或者引用调用这个虚函数。  ...(基类与派生类虚函数返回值类型不同) 派生类重写基类虚函数,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为。...有些选择题可能会出,虚函数重写的返回值类型不一定相同,就是一个例外。...如果使用基类的指针指向一个派生类,就会出现内存泄漏的情况,因为派生类的析构函数并没有调用。解决方法就是让派生类和基类的析构函数完成重写

    6210

    3分钟快速搞懂Java的桥接方法

    返回类型 返回类型是指子类方法的返回值类型不必严格等同于父类中被重写方法的返回值类型,而可以是更 "具体" 的类型。...在Java 1.5添加了对返回类型的支持,即子类重写父类方法,返回的类型可以是子类方法返回类型的子类。...因为在JVM方法中,返回类型也是方法签名的一部分,而桥接方法的签名和其父类的方法签名一致,以此就实现了返回值类型。...类型擦除 泛型是Java 1.5才引进的概念,在这之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容,这是为什么呢?...一个子类在继承(或实现)一个父类(或接口)的泛型方法,在子类中明确指定了泛型类型,那么在编译编译器会自动生成桥接方法,例如: public class Parent { void

    31050

    3分钟快速搞懂Java的桥接方法

    返回类型 返回类型是指子类方法的返回值类型不必严格等同于父类中被重写方法的返回值类型,而可以是更 “具体” 的类型。...在Java 1.5添加了对返回类型的支持,即子类重写父类方法,返回的类型可以是子类方法返回类型的子类。...**因为在JVM方法中,返回类型也是方法签名的一部分,而桥接方法的签名和其父类的方法签名一致,以此就实现了返回值类型。...类型擦除 泛型是Java 1.5才引进的概念,在这之前是没有泛型的概念的,但泛型代码能够很好地和之前版本的代码很好地兼容,这是为什么呢?...一个子类在继承(或实现)一个父类(或接口)的泛型方法,在子类中明确指定了泛型类型,那么在编译编译器会自动生成桥接方法,例如: public class Parent { void

    73541

    【C++】多态

    举个栗子: 比如买票这个行为,普通人买票,是全价买票;学生买票,是半价买票;军人买票是优先买票。...注意⚠: 在重写基类虚函数,派生类的虚函数不加virtual关键字,也可以构成重写(可以认为继承后基类的虚函数继承下来了在派生类中依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用 但是父类的...3.2 虚函数重写的第二个例外: 派生类重写基类虚函数,与基类虚函数返回值类型可以不同。...但是是有要求的: 基类虚函数必须返回基类对象的指针或引用,派生类虚函数必须返回派生类对象的指针或引用,我们把这种情况称为。...它定义了一组方法和行为,但并没有具体的实现细节。你可以把它看作是一个规范,告诉其他类应该有哪些方法,并且如何使用这些方法

    11110

    【C++深度探索】全面解析多态性机制(一)

    通俗来说,就是多种形态,或者说完成某个行为时,不同的对象去完成会产生出不同的状态。 例如:买票这个行为,普通人买票,是全价买票;学生买票,是半价买票;军人买票是优先买票。...在继承中构成多态有两个条件: 必须通过基类的指针或者引用调用虚函数 调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写 例如: class Person { public: virtual...4.虚函数重写的两个例外 (基类与派生类虚函数返回值类型不同) 即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为。...前面我们学习过虚函数重写必须要求基类与派生类除了函数体以外其它完全相同,但是对于,基类与派生类的返回值类型可以不同,但基类与派生类的函数的返回类型必须是继承关系 // class A {};...结果如下: 这里要注意派生类的析构调用完之后会自动调用基类对象的析构函数,所以这里基类的析构函数调用了两次 我们可以对比一下,没有实现多态,对于delete对象调用析构函数是不会根据所指向的对象调用相应的析构函数

    11410

    【C++】———— 多态

    二、多态的定义和实现 1.多态构成条件 在继承中形成多态还有两个条件: 调用时必须要通过基类的指针或者引用调用虚函数 调用的函数必须是虚函数,且派生类必须含有对基类的虚函数的重写 这里我们插入一个概念...权限要求不同:重载对访问权限没有要求,重写要求子类中的重写函数不能比父类中的重写函数有更严格的访问权限。 与虚函数的关系:重载与虚函数无关,重写的函数通常是父类中的虚函数。...,派生类的虚函数在不加virtual关键字,虽然也可以构成重写(因为继承后基类的虚函数继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样写 2.虚函数的重写和协 上面例子中...虚函数重写的两个例外: 2.1 派生类重写基类虚函数,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指 针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为。...,分别在基类和派生类 4.final 和 override 添加在父类虚函数后面添加final代表不能再被重写 final修饰类,代表不能继承: override代表必须要重写虚函数,如果没有重写便会报错

    10510

    为什么要把类设置成密封?

    性能优势 虚方法调用 在上面提到的文章例子中,有一个虚方法的调用,大家其实明白一点,现在面向对象的封装、继承、多态中的多态实现主要就是靠虚方法。...一个类型可能会有子类,子类可能会重写类型的方法从而达到不同的行为(多态),而这些重写方法都在虚方法表里,调用的话就需要查表。.... // 它可能已经另一个方法设置为派生类。 // 所以,为了安全起见,它必须使用一个虚拟调用。...我们可以看到 JIT 生成后的汇编代码,可以很清楚的看到密封类少了两条指令,因为 JIT 可以从密封类中知道它不可能继承,也不可能重写,所以是直接跳转到密封类目标方法执行,而非密封类还有一个查表的过程...IL 层面,两个方法都是一模一样: 可以看到密封类的代码相当高效,直接比较一下就转换类型返回了,而非密封类还需要 call 方法走查表流程: 数组 .NET 的数组是的,兼容的话就意味着在添加进入数组需要检查它的类型

    32520

    Kotlin | 9. 泛型

    本章内容包括: 声明泛型函数和类 类型擦除和实化类型参数 声明点变型和使用点变型 9.1 泛型类型参数 // 如果创建一个空的列表,必须显示的指定,有值的话可以推导出来...// 声明类在某个类型参数上是可的,在该类型参数的名称前加上 out 关键字即可 // interface Producer{ // fun produce...9.11 定义一个不变型的类似集合的类 open class Animal { fun feed() {} } // 类型参数没有声明成的...get,而没有定义任何类型为T的元素存储到列表中的方法,因为它是的。...在Kotlin 中既可以为整个泛型类指定变型(声明点变型),也可以为泛型类型特定的使用指定变型(使用点变型)。 确切的类型实参是未知的或者不重要的时候,可以使用星号投影语法。

    1.8K10

    Java漫谈-返回类型

    Java SE5中添加返回类型,表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型。...Mill的process()方法 * 返回类型允许返回更具体的Wheat类型,亦即此时的Wheat为返回类型 * @return */ Wheat process...返回类型允许返回更具体的Wheat类型 扩: 里氏代换原则(任何基类可以出现的地方,子类一定可以出现) 重写/覆盖规则:  1.重写方法不能比重写方法限制有更严格的访问级别。...2.参数列表必须与重写方法的相同。 3.返回类型必须与重写方法的返回类型相同。 4.重写方法不能抛出新的异常或者比重写方法声明的检查异常更广的检查异常。但是可以抛出更少,更有限或者不抛出异常。...5.不能重写标识为final的方法。 6.如果一个方法不能继承,则不能重写它。

    1K10

    《Kotlin 极简教程 》第6章 泛型

    6.1.1 为什么要有类型参数 我们先来看下没有泛型之前,我们的集合类是怎样持有对象的。 在Java中,Object类是所有类的根类。为了集合类的通用性。...pairs: Pair): Map 类型参数K,V是一个占位符,泛型类型实例化和使用时,它将被一个实际的类型参数所替代。...那么我们可以这么来描述和逆F <| C , 如果有f(F) <| f(C),那么f叫做(Convariant); F <| C , 如果有f(C) <| f(F),那么f叫做逆...和逆都是类型安全的。 Java中泛型是不变的,可有时需要实现逆,怎么办呢?这时就需要使用我们上面讲的通配符? 。 实现了泛型的 List<?...我们应该尽量使用泛型方法,也就是说如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法,因为它可以使事情更明白。 本章小结 泛型是一个非常有用的东西。尤其在集合类中。

    1.7K30

    【C++】多态(定义、虚函数、重写、隐藏)

    继承中构成多态还有两个条件: 必须通过基类的指针或者引用调用虚函数 调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写 如果是通过基类的指针调用虚函数,如下图所示使用: 虚函数 虚函数...注意:在重写基类虚函数,派生类的虚函数在不加virtual关键字,虽然也可以构成重写(因 为继承后基类的虚函数继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用 虚函数重写的两个例外...: (基类与派生类虚函数返回值类型不同) 派生类重写基类虚函数,与基类虚函数返回值类型不同。...p指向johnson对象,找到就是Student::BuyTicket。 如果我们达到多态,有两个条件,一个是虚函数覆盖,一个是对象的指针或引用调 用虚函数。...结论:使用父类对象调用的方法永远是父类的方法 2.

    15310

    C#泛型的逆之个人理解

    object> list = new List(); 这个为什么就可以 A:   这就要讲到C#泛型里的逆变了 Q:   细嗦细嗦 逆 C#泛型中的逆(in)(out)对于不常自定义泛型的开发来说..., 可以进行符合直觉且和谐的转化 前编中提到的代码例子不适用并且也不能改造成, 只适合使用 相比于符合直觉且和谐的, 逆是不符合直觉并且别扭的 IFace item = new...类型, 而实际上最终调用的 Face.Print 是支持 object 的, 传入 string 类型的参数没有任何问题 逆的作用 逆(in)(out)的作用就是扩展泛型的用法...A:   简单来说, 有关泛型输入的用逆, 关键词是in, 有关泛型输出的用, 关键词是out, 如果接口中既有输入又有输出, 就不能用逆 Q:   为什么这两个不能同时存在?...A:   的表现形式为将子类赋值给基类, 进行输出相关操作, 输出的对象类型为基类, 是将子类转为基类, 你可以说子类是基类; 逆的表现形式为将基类赋值给子类, 进行输入相关操作, 输入的对象为子类

    18920

    、逆与不变

    Java 并没有提供类型的变声明,取而代之的是在使用时的类型限制,形式大概是这样: List students = new ArrayList(); students.add(new...这就保证了集合的要求。也就是说,Java 选择不在参数化类型声明的时候去声明该类型的型关系,而是选择在这个类型使用的时候去进行限定。...,由此就能理解为什么函数类型相对于其参数的类型是逆的了。...为什么数组是不变的?因为数组上的每个单元都相当于包含了两个方法写下 T value = arr[3] 这样的代码,概念上可以理解为 T value = arr3.get()。...在 Scala 中,如果进行了或者逆的标记,编译器就会对这个类型参数的使用进行检查,如果它出现在了错误的位置上,编译器就会提示错误,防止了开发者因此而犯错。

    1.8K30

    C++中的多态

    (基类与派生类虚函数返回值类型不同) 三同中,返回值可以不同,但是要求返回值必须是一个父子类关系的指针或者引用。...这里可以小小地总结两点,关于需要写出一个不能继承的类。 ①私有构造函数;②final修饰类 override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。...因此,多态的原理就是: (这里再用Person类、Student类举例子) 基类指针Person*或引用Perosn&指向派生类对象,在调用重写的虚函数,就会到指向的对象的类里面找虚表!...反思构成多态的条件 通过分析,我们可以好好反思一下构成多态的条件,为什么虚函数重写为什么基类对象的指针或引用调用虚函数。 ①为什么虚函数覆盖/重写: 因为要对派生类的虚表进行覆盖。...在调用重写的函数的时候,如果指向的是派生类对象,那么就必须从这个派生类的虚表中拿到这个虚函数的地址。 ②为什么基类对象的指针或引用去调用虚函数: 首先,虚函数必须写在基类中。

    83420
    领券