写点什么

11 种编程语言中,返回多个不同类型的方法样例

  • 2023-12-14
    广东
  • 本文字数:6022 字

    阅读完需:约 20 分钟

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"  endend
class Monkey < Animal def to_s "I am a monkey" endend
class Cow < Animal def to_s "I am a cow" endend
def create_animal(animal_type) case animal_type when "Monkey" Monkey.new when "Cow" Cow.new else raise "Unknown animal type: #{animal_type}" endend
begin animal1 = create_animal("Monkey") if animal1.is_a? Monkey puts animal1 end
animal2 = create_animal("Cow") if animal2.is_a? Cow puts animal2 endend
复制代码

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);}
复制代码

点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
11种编程语言中,返回多个不同类型的方法样例_编程语言_华为云开发者联盟_InfoQ写作社区