ios 命名为现有对象添加扩展名的 Swift 文件的最佳实践是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26319660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:08:32  来源:igfitidea点击:

What's the best practice for naming Swift files that add extensions to existing objects?

iosobjective-cswiftxcode

提问by AlBlue

It's possible to add extensions to existing Swift object types using extensions, as described in the language specification.

可以使用扩展向现有 Swift 对象类型添加扩展,如语言规范中所述

As a result, it's possible to create extensions such as:

因此,可以创建扩展,例如:

extension String {
    var utf8data:NSData {
        return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    }
}

However, what's the best naming practice for Swift source files containing such extensions?

但是,包含此类扩展名的 Swift 源文件的最佳命名实践是什么?

In the past, the convention was to use extendedtype+categoryname.mfor the Objective-C type as discussed in the Objective-C guide. But the Swift example doesn't have a category name, and calling it String.swiftdoesn't seem appropriate.

过去,约定extendedtype+categoryname.m用于 Objective-C 类型,如Objective-C 指南中所述。但是 Swift 示例没有类别名称,调用它String.swift似乎不合适。

So the question is: given the above Stringextension, what should the swift source file be called?

那么问题来了:鉴于上面的String扩展名,swift源文件应该叫什么?

回答by picciano

Most examples I have seen mimic the Objective-C approach. The example extension above would be:

我见过的大多数示例都模仿了 Objective-C 方法。上面的示例扩展将是:

String+UTF8Data.swift

String+UTF8Data.swift

The advantages are that the naming convention makes it easy to understand that it is an extension, and which Class is being extended.

优点是命名约定使得很容易理解它是一个扩展,以及扩展的是哪个类。

The problem with using Extensions.swiftor even StringExtensions.swiftis that it's not possible to infer the purpose of the file by its name without looking at its contents.

使用Extensions.swift或什至的问题StringExtensions.swift在于,如果不查看其内容,就无法通过名称推断文件的用途。

Using xxxable.swiftapproach as used by Java works okay for protocols or extensions that only define methods. But again, the example above defines an attribute so that UTF8Dataable.swiftdoesn't make much grammatical sense.

xxxable.swift对于仅定义方法的协议或扩展,使用 Java使用的方法可以正常工作。但同样,上面的示例定义了一个属性,因此在UTF8Dataable.swift语法上没有太大意义。

回答by Mike Taverne

There is no Swift convention. Keep it simple:

没有 Swift 约定。把事情简单化:

StringExtensions.swift

I create one file for each class I'm extending. If you use a single file for all extensions, it will quickly become a jungle.

我为我要扩展的每个类创建一个文件。如果所有扩展名都使用一个文件,它很快就会变成丛林。

回答by DawnSong

I prefer StringExtensions.swiftuntil I added too much things to split the file into something like String+utf8Data.swiftand String+Encrypt.swift.

我更喜欢StringExtensions.swift直到我添加了太多东西来将文件拆分为类似String+utf8Data.swift和 的内容String+Encrypt.swift

One more thing, to combine similar files into one will make your building more faster. Refer to Optimizing-Swift-Build-Times

还有一件事,将类似的文件合并为一个将使您的构建速度更快。请参阅优化 Swift 构建时间

回答by Tom Condon

Why is this even a debate? Should I put all my sub classes into a file called _Subclasses.swift. I think not. Swift has module based name spacing. To extend a well known Swift class needs a file that is specific to its purpose. I could have a large team that creates a file that is UIViewExtensions.swift that express no purpose and will confuse developers and could be easily duplicated in the project which would not build. The Objective-C naming convention works fine and until Swift has real name spacing, it is the best way to go.

为什么这甚至是一场辩论?我应该将所有子类放入一个名为 _Subclasses.swift 的文件中吗?我想不是。Swift 具有基于模块的名称间距。要扩展众所周知的 Swift 类,需要一个特定于其用途的文件。我可以有一个庞大的团队来创建一个 UIViewExtensions.swift 文件,该文件没有任何目的,会使开发人员感到困惑,并且很容易在无法构建的项目中复制。Objective-C 命名约定工作正常,并且在 Swift 具有真正的名称间距之前,这是最好的方法。

回答by Mark A. Donohoe

Rather than adding my comments all over the place, I'm surfacing them all here in one answer.

我没有在所有地方添加我的评论,而是在一个答案中将它们全部显示出来。

Personally, I take a hybrid approach that gives both good usability and clarity, while also not cluttering up the API surface area for the object that I'm extending.

就我个人而言,我采用了一种混合方法,既提供了良好的可用性和清晰度,同时也不会使我正在扩展的对象的 API 表面区域变得混乱。

For instance, anything that makes senseto be available to anystring would go in StringExtensions.swiftsuch as trimRight()and removeBlankLines().

例如,任何有意义的是提供给任何字符串会去StringExtensions.swifttrimRight()removeBlankLines()

However, if I had an extension function such as formatAsAccountNumber()it would notgo in that file because 'Account Number' is not something that would naturally apply to any/all strings and only makes sense in the context of accounts. In that case, I would create a file called Strings+AccountFormatting.swiftor maybe even Strings+CustomFormatting.swiftwith a formatAsAccountNumber()function if there are several types/ways to actually format it.

但是,如果我有一个扩展函数,例如formatAsAccountNumber()不会出现在该文件中,因为“帐号”不是自然适用于任何/所有字符串的东西,并且仅在帐户上下文中才有意义。在这种情况下,如果有多种类型/方法来实际格式化它,我会创建一个名为的文件,Strings+AccountFormatting.swift或者甚至可能Strings+CustomFormatting.swift使用一个formatAsAccountNumber()函数。

Actually, in that last example, I actively dissuade my team from using extensions like that in the first place, and would instead encourage something like AccountNumberFormatter.format(String)instead as that doesn't touch the StringAPI surface area at all, as it shouldn't. The exception would be if you defined that extension in the same file where it's used, but then it wouldn't have it's own filename anyway.

实际上,在最后一个例子中,我一开始就积极劝阻我的团队不要使用这样的扩展,而是鼓励使用类似的东西,AccountNumberFormatter.format(String)因为它根本不接触StringAPI 表面区域,因为它不应该这样做。例外情况是,如果您在使用它的同一个文件中定义了该扩展名,但无论如何它都不会有自己的文件名。

回答by Xys

I prefer having a +to underline the fact it contains extensions :

我更喜欢+强调它包含扩展的事实:

String+Extensions.swift

String+Extensions.swift

And if the file gets too big, you can then split it for each purpose :

如果文件太大,您可以针对每个目的拆分它:

String+UTF8Data.swift

String+UTF8Data.swift

String+Encrypt.swift

String+Encrypt.swift

回答by Faisal Memon

If you have a team-agreed set of common and miscellaneous enhancements, lumping them together as an Extensions.swift works as Keep-It-Simple first level solution. However, as your complexity grows, or the extensions become more involved, a hierarchy is needed to encapsulate the complexity. In such circumstances I recommend the following practice with an example.

如果您有一组团队同意的通用和杂项增强功能,请将它们作为一个 Extensions.swift 集中在一起作为 Keep-It-Simple 一级解决方案。但是,随着您的复杂性增加,或者扩展变得更加复杂,需要一个层次结构来封装复杂性。在这种情况下,我建议使用以下示例进行练习。

I had a class which talks to my back-end, called Server. It started to grow bigger to cover two different target apps. Some people like a large file but just logically split up with extensions. My preference is to keep each file relatively short so I chose the following solution. Serveroriginally conformed to CloudAdapterProtocoland implemented all its methods. What I did was to turn the protocol into a hierarchy, by making it refer to subordinate protocols:

我有一个与我的后端对话的类,称为Server. 它开始变得更大以涵盖两个不同的目标应用程序。有些人喜欢大文件,但只是在逻辑上与扩展名分开。我的偏好是保持每个文件相对较短,因此我选择了以下解决方案。 Server最初符合CloudAdapterProtocol并实现了它的所有方法。我所做的是将协议变成层次结构,通过使其引用从属协议:

protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
    var server: CloudServer {
        get set
    }
    func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void)
}

In Server.swiftI have

Server.swift我有

import Foundation
import UIKit
import Alamofire
import AlamofireImage

class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) {
.
.
}

Server.swiftthen just implements the core server API for setting the server and getting the API version. The real work is split into two files:

Server.swift然后只需实现用于设置服务器和获取 API 版本的核心服务器 API。真正的工作分为两个文件:

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

These implement the respective protocols.

这些实现了各自的协议。

It means you need to have import declarations in the other files (for Alamofire in this example) but its a clean solution in terms of segregating interfaces in my view.

这意味着您需要在其他文件中有导入声明(在本例中为 Alamofire),但在我看来,它是隔离接口的一个干净的解决方案。

I think this approach works equally well with externally specified classes as well as your own.

我认为这种方法适用于外部指定的类以及您自己的类。