本文分享自华为云社区《多语言编程 返回多个不同类型的方法样例》,作者: 张俭 。
背景
你可能会在一些场景下碰到需要返回多个不同类型的方法。比如协议解析读取报文时,更具体地像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;
- }
复制代码 使用SealedClass
- 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)
- }
- }
复制代码 Python
Python是动态类型的语言,可以简单基于一些条件返回不同类型的对象,然后在接收到返回值之后使用type()函数或isinstance()函数来确定其类型- 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);
- }
- }
- }
复制代码 Ruby
Ruby也较为简单,在方法内部直接返回不同类型的对象。然后,可以使用is_a方法或class方法来确定返回对象的实际类型。- 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);
- }
复制代码 Rust
在Rust中,可以使用enum(枚举)来创建一个持有多种不同类型的数据结构。然后使用match语句来做模式匹配。
[code]use std::fmt;enum Animal { Monkey, Cow,}impl fmt: isplay for Animal { fn fmt(&self, f: &mut fmt::Formatter |