乱弹:Swift单复共体参数类型---与Ruby相比不那么优雅的实现

版权声明:大熊猫猪·侯佩原创或翻译作品.谢绝转载! hopy https://blog.csdn.net/mydo/article/details/85916279

本文提出单复共体参数的一种实现,同时比较了Ruby中的实现,后者显然更加优雅。适合对Swift语言本身有兴趣,喜欢纠结语法,而且了解其他动态语言的童鞋观看。

什么是单复共体参数?

这是我发明的词…

很简单,就是对于同一类型的对象,既可以传递它的单数形式又可以传递它的复数形式作为方法的参数。

在这里插入图片描述

还是一头雾水???举个栗子:

//display(...)是一个方法,现在还不知道它的原型应该怎么写,但希望如下几种方式都可以调用:

display("A")
display(["A","B"])
display("X","Y")

现在有点明白了吗?只要display方法的形参类型确定下来(String),可以传递任何数量的String对象给他。

第一次尝试

因为Swift的枚举可以自带附加值,所以先用它来试试:

enum ItemType<Item>{
    case one(Item)
    case many([Item])
}

func display(_ strings:ItemType<String>){
    
    var msg = [String]()
    
    switch strings{
    case .one(let string):
        msg.append(string)
    case .many(let ary):
        msg.append(contentsOf: ary)
    }
    
    print(msg.joined(separator: " , "))
}

//这样调用
display(.one("hallo"))
display(.many(["1","3","5"]))

貌似怪怪的…而且无法实现display第三种形态的调用,因为枚举附带类型不可以这么写:

case many(Item...)

插曲

我不知道你们怎么想,反正我第一反应就是使用OptionSet类型的对象。

还记得UIView动画参数么?下面两种调用都是合法的:

UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: {}, completion: nil)

UIView.animate(withDuration: 0.5, delay: 0.0, options: [.curveEaseIn], animations: {}, completion: nil)

但遗憾的是,OptionSet背后实际是用一个Int类型的RawValue来施展魔法,无法满足任意类型。

(如果真的可以,请赐教…)

一种调皮的实现

如果"无耻"到极点,可以这么写:

func display(_ strings:Any){
	//do what you want...
}

如果你是老实人,就得受点累,手动把某种类型所有形式都写一遍:

func display(_ string:String){
    print(string)
}

func display(_ strings:[String]){
    print(strings.joined(separator: " , "))
}

func display(_ strings:String...){
    print(strings.joined(separator: " , "))
}

上面可以达成目的,但不优雅…

第二次尝试

泛型在任何语言中都不是吃素的,在Swift里也是如此,我们可以这么写:

class _T<Item>{
    private(set) var items = [Item]()
    
    init(_ item:Item) {
        items.append(item)
    }
    
    init(_ items:[Item]) {
        self.items.append(contentsOf: items)
    }
    
    init(_ items:Item...){
        self.items.append(contentsOf: items)
    }
}

func display(_ items:_T<String>){
    print(items.items)
}

//下面几种调用都合法
display(_T("a"))
display(_T(["A","B"]))
display(_T("X","Y"))

这是目前为止,在Swift中我想到的最优雅的实现方法…

在这里插入图片描述

最优雅的实现—Ruby参数聚合

ruby对于方法的参数有非常实用的“聚合”和“打散”概念,这里只用到前者:

2.2.6 :001 > def display(*item)
2.2.6 :002?>   print(item.flatten)
2.2.6 :003?> end
 => :display 
2.2.6 :004 > display("a")
["a"] => nil 
2.2.6 :005 > display("a","b")
["a", "b"] => nil 
2.2.6 :006 > display(["a","b"])
["a", "b"] => nil 

这种简单真是优雅到了极点…

注意display形参前面*号是其精髓所在,它的意思是:将所有传递给display方法的参数“聚合”起来,俗称“打包”,变为一个数组,然后使用。

这样我无论如何传递什么进去都没问题!

你可能会问上面怎么没有类型检查???

因为Ruby有两大核心要诀:

  1. 鸭式冲击
  2. 猴打补丁

因为前者,所以没有必要做检查。

什么又是鸭,又是猴的…你是胡诌的吧…

你猜猜… 😉

在这里插入图片描述

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试