11种编程语言中,返回多个不同类型的方法样例
本文分享自华为云社区《多语言编程 返回多个不同类型的方法样例》,作者: 张俭 。
背景
你可能会在一些场景下碰到需要返回多个不同类型的方法。比如协议解析读取报文时,更具体地像kubernetes在开始解析Yaml的时候,怎么知道这个类型是属于Deployment还是Service?
C
C语言通常通过使用Struct(结构体)和Union(联合体)的方式来实现这个功能,如下文例子
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef enum { MONKEY, COW, UNKNOWN } AnimalType; typedef struct { char* description; } Monkey; typedef struct { char* description; } Cow; typedef struct { AnimalType type; union { Monkey monkey; Cow cow; }; } Animal; Animal createAnimal(const char* animalType) { Animal animal; if (strcmp(animalType, "Monkey") == 0) { animal.type = MONKEY; animal.monkey.description = "I am a monkey!"; } else if (strcmp(animalType, "Cow") == 0) { animal.type = COW; animal.cow.description = "I am a cow!"; } else { animal.type = UNKNOWN; } return animal; } int main() { Animal animal1 = createAnimal("Monkey"); if (animal1.type == MONKEY) { printf("%s\n", animal1.monkey.description); } Animal animal2 = createAnimal("Cow"); if (animal2.type == COW) { printf("%s\n", animal2.cow.description); } Animal animal3 = createAnimal("Dog"); if (animal3.type == UNKNOWN) { printf("Unknown animal type\n"); } return 0; }
C++
在C++中,我们可以使用基类指针来指向派生类的对象。可以使用动态类型识别(RTTI)来在运行时确定对象的类型
#include <iostream> #include <stdexcept> class Animal { public: virtual std::string toString() const = 0; }; class Monkey : public Animal { public: std::string toString() const override { return "I am a monkey!"; } }; class Cow : public Animal { public: std::string toString() const override { return "I am a cow!"; } }; Animal* createAnimal(const std::string& animalType) { if (animalType == "Monkey") { return new Monkey(); } if (animalType == "Cow") { return new Cow(); } throw std::runtime_error("Unknown animal type: " + animalType); } int main() { try { Animal* animal1 = createAnimal("Monkey"); if (Monkey* monkey = dynamic_cast<Monkey*>(animal1)) { std::cout << monkey->toString() << std::endl; } delete animal1; Animal* animal2 = createAnimal("Cow"); if (Cow* cow = dynamic_cast<Cow*>(animal2)) { std::cout << cow->toString() << std::endl; } delete animal2; } catch (const std::runtime_error& e) { std::cerr << e.what() << std::endl; } return 0; }
Go
Go的常见处理方式,是返回一个接口或者**interface{}**类型。调用者使用Go语言类型断言来检查具体的类型
package main import ( "fmt" ) type Animal interface { String() string } type Monkey struct{} func (m Monkey) String() string { return "I am a monkey!" } type Cow struct{} func (c Cow) String() string { return "I am a cow!" } func createAnimal(typeName string) (Animal, error) { switch typeName { case "Monkey": return Monkey{}, nil case "Cow": return Cow{}, nil default: return nil, fmt.Errorf("Unknown animal type: %s", typeName) } } func main() { animal1, err := createAnimal("Monkey") if err != nil { fmt.Println(err) return } if monkey, ok := animal1.(Monkey); ok { fmt.Println(monkey) } animal2, err := createAnimal("Cow") if err != nil { fmt.Println(err) return } if cow, ok := animal2.(Cow); ok { fmt.Println(cow) } }
Java
Java语言的常见处理方式,是返回Object类型或者一个基础类型。然后由调用方在进行instance of判断。或者Java17之后,可以使用模式匹配的方式来简化转型
public class MultiTypeReturnExample { static class Monkey { @Override public String toString() { return "I am a monkey!"; } } static class Cow { @Override public String toString() { return "I am a cow!"; } } public static Object createAnimal(String type) throws IllegalArgumentException { switch (type) { case "Monkey": return new Monkey(); case "Cow": return new Cow(); default: throw new IllegalArgumentException("Unknown animal type: " + type); } } public static void main(String[] args) throws Exception { Object animal1 = createAnimal("Monkey"); // java8 写法,后面如果明确用做精确的类型,需要强制转换 if (animal1 instanceof Monkey) { System.out.println(animal1); } Object animal2 = createAnimal("Cow"); if (animal2 instanceof Cow) { System.out.println(animal2); } // java17 写法,不需要强制转换 if (createAnimal("Monkey") instanceof Monkey animal3) { System.out.println(animal3); } if (createAnimal("Cow") instanceof Cow animal4) { System.out.println(animal4); } } }
Javascript
动态类型语言,使用instanceof运算符判断
class Animal { toString() { return 'I am an animal'; } } class Monkey extends Animal { toString() { return 'I am a monkey'; } } class Cow extends Animal { toString() { return 'I am a cow'; } } function createAnimal(animalType) { switch (animalType) { case 'Monkey': return new Monkey(); case 'Cow': return new Cow(); default: throw new Error(`Unknown animal type: ${animalType}`); } } try { const animal1 = createAnimal('Monkey'); if (animal1 instanceof Monkey) { console.log(animal1.toString()); } const animal2 = createAnimal('Cow'); if (animal2 instanceof Cow) { console.log(animal2.toString()); } const animal3 = createAnimal('Dog'); } catch (error) { console.error(error.message); }
Kotlin
Kotlin可以使用Sealed Class(密封类)和Any类型两种方式。使用Any的场景,与Java返回Object类似。Sealed Class更加安全、更方便一些。
使用Any类型
open class Animal class Monkey: Animal() { override fun toString(): String { return "I am a monkey!" } } class Cow: Animal() { override fun toString(): String { return "I am a cow!" } } fun createAnimal(type: String): Any { return when (type) { "Monkey" -> Monkey() "Cow" -> Cow() else -> throw IllegalArgumentException("Unknown animal type: $type") } } fun main() { val animal1 = createAnimal("Monkey") when (animal1) { is Monkey -> println(animal1) is Cow -> println(animal1) } val animal2 = createAnimal("Cow") when (animal2) { is Monkey -> println(animal2) is Cow -> println(animal2) } }
使用SealedClass
sealed class Animal { data class Monkey(val info: String = "I am a monkey!") : Animal() data class Cow(val info: String = "I am a cow!") : Animal() } fun createAnimal(type: String): Animal { return when (type) { "Monkey" -> Animal.Monkey() "Cow" -> Animal.Cow() else -> throw IllegalArgumentException("Unknown animal type: $type") } } fun main() { val animal1 = createAnimal("Monkey") when (animal1) { is Animal.Monkey -> println(animal1.info) is Animal.Cow -> println(animal1.info) } val animal2 = createAnimal("Cow") when (animal2) { is Animal.Monkey -> println(animal2.info) is Animal.Cow -> println(animal2.info) } }
Python
Python是动态类型的语言,可以简单基于一些条件返回不同类型的对象,然后在接收到返回值之后使用type()函数或isinstance()函数来确定其类型
class Animal: def __str__(self): return "I am an animal" class Monkey(Animal): def __str__(self): return "I am a monkey" class Cow(Animal): def __str__(self): return "I am a cow" def create_animal(animal_type): if animal_type == "Monkey": return Monkey() elif animal_type == "Cow": return Cow() else: raise ValueError(f"Unknown animal type: {animal_type}") def main(): animal1 = create_animal("Monkey") if isinstance(animal1, Monkey): print(animal1) animal2 = create_animal("Cow") if isinstance(animal2, Cow): print(animal2) if __name__ == "__main__": main()
Ruby
Ruby也较为简单,在方法内部直接返回不同类型的对象。然后,可以使用is_a方法或class方法来确定返回对象的实际类型。
class Animal def to_s "I am an animal" end end class Monkey < Animal def to_s "I am a monkey" end end class Cow < Animal def to_s "I am a cow" end end def create_animal(animal_type) case animal_type when "Monkey" Monkey.new when "Cow" Cow.new else raise "Unknown animal type: #{animal_type}" end end begin animal1 = create_animal("Monkey") if animal1.is_a? Monkey puts animal1 end animal2 = create_animal("Cow") if animal2.is_a? Cow puts animal2 end end
Rust
在Rust中,可以使用enum(枚举)来创建一个持有多种不同类型的数据结构。然后使用match语句来做模式匹配。
use std::fmt; enum Animal { Monkey, Cow, } impl fmt::Display for Animal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Animal::Monkey => write!(f, "I am a monkey!"), Animal::Cow => write!(f, "I am a cow!"), } } } fn create_animal(animal_type: &str) -> Result<Animal, String> { match animal_type { "Monkey" => Ok(Animal::Monkey), "Cow" => Ok(Animal::Cow), _ => Err(format!("Unknown animal type: {}", animal_type)), } } fn main() { match create_animal("Monkey") { Ok(animal) => match animal { Animal::Monkey => println!("{}", animal), _ => (), }, Err(e) => println!("{}", e), } match create_animal("Cow") { Ok(animal) => match animal { Animal::Cow => println!("{}", animal), _ => (), }, Err(e) => println!("{}", e), } match create_animal("Dog") { Ok(_) => (), Err(e) => println!("{}", e), } }
Scala
scala中,可以使用sealed trait和case class来创建一个能够返回多种不同类型的方法。Sealed trait可以定义一个有限的子类集合,可以确保类型安全
sealed trait Animal { def info: String } case class Monkey() extends Animal { val info: String = "I am a monkey!" } case class Cow() extends Animal { val info: String = "I am a cow!" } object MultiTypeReturnExample { def createAnimal(animalType: String): Animal = { animalType match { case "Monkey" => Monkey() case "Cow" => Cow() case _ => throw new IllegalArgumentException(s"Unknown animal type: $animalType") } } def main(args: Array[String]): Unit = { try { val animal1 = createAnimal("Monkey") animal1 match { case Monkey() => println(animal1.info) case _ => } val animal2 = createAnimal("Cow") animal2 match { case Cow() => println(animal2.info) case _ => } } catch { case e: IllegalArgumentException => println(e.getMessage) } } }
TypeScript
总得来说,和javascript区别不大
abstract class Animal { abstract toString(): string; } class Monkey extends Animal { toString(): string { return 'I am a monkey'; } } class Cow extends Animal { toString(): string { return 'I am a cow'; } } function createAnimal(animalType: string): Animal { switch (animalType) { case 'Monkey': return new Monkey(); case 'Cow': return new Cow(); default: throw new Error(`Unknown animal type: ${animalType}`); } } try { const animal1 = createAnimal('Monkey'); if (animal1 instanceof Monkey) { console.log(animal1.toString()); } const animal2 = createAnimal('Cow'); if (animal2 instanceof Cow) { console.log(animal2.toString()); } const animal3 = createAnimal('Dog'); } catch (error) { console.error(error.message); }

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
数据库圈的夜郎自大,危!
作者:尹海文,Oracle ACE,OCM 11g/12c/19c,MySQL 8.0 OCP,墨天轮MVP、技术专家,ITPUB核心专家,OCM讲师,网思科技DBA总监。 微信公众号:胖头鱼的鱼缸 今天看到薛首席在OSCHINA邀稿的一篇文章《国产数据库的出现和消失,都不是技术问题》及其评论,感触颇多,忍不住得写一篇文章。 0和1的艺术 现在计算机,归根结底是二极管的使用艺术,即开与合,0和1,运行在硬件之上无论是操作系统、软件还是其他什么的,都是对二进制的使用,本质还是和数学打交道。以数据库为例,其中的各项算法都得和这最基础的数学打交道,涉及基本的二进制、硬件固件、硬件指令集、硬件驱动等等与软件运行之间的结合。我一直没搞懂总有人在说,近几十年来很多涉及数据库数学层面的东西没有进步,我们随随便便就能赶超?! 我是一个高中文科大学园林设计专业的DBA,我无法从深层次的数学层面来解释一些东西,但是我可以通过一些方法来展现结果:安安分分用相同的配置在Oracle 11g vs 19c、MySQL 5.6 vs 8.0、PG 9 vs 16跑跑完全相同的东西,抹平所谓的硬件带来的进步,看看性...
- 下一篇
【直播预告】上云 vs 下云:降本增笑?割韭菜?
本月,滴滴崩溃事件闹得轰轰烈烈,各种离谱派单层出不穷,而造成这一混乱的,则是底层出故障的阿里云。尴尬的是,这已经不是它第一次崩溃了,距离上一次,还不到一个月。 一时之间,各种有关“云”的讨论纷纷扬扬:有人眼馋马斯克的 X 下云省钱,觉得反正都有风险,还不如自己弄,这样更可掌控,也更清楚;有人则认为上云才是未来的趋势,想要发挥出软件的最大优势,上云更合适。 那么,你怎么看呢—— 公有云崩溃,到底是必然事件,还是事出偶然? X 的案例参考性有多大?想省钱是该上云 or 下云呢? 到底是自建云更安全,还是公有云更有保障? 对普通的厂商而言,该怎么选择呢? 本期,OSCHINA【开源漫谈】特地邀请了 5 位业内具有代表性的专家,直播探讨一下,接下来,我们该上云还是下云? 直播主题:上云 vs 下云:降本增笑?割韭菜? 直播时间:12 月 20 日 19:00 - 20:30 直播平台:“OSC 开源社区”视频号 主办方:开源中国 直播嘉宾: 主持人: 李鹤,kinitiras、kluster-capacity 作者,kubernetes、karmada 社区贡献者,前滴滴软件开发工程师。1...
相关文章
文章评论
共有0条评论来说两句吧...