在 Swift 中,模块是指什么?

34

举个例子,我有两个文件叫做file1.swiftfile2.swift

file1.swift:

import UIKit

class A: B {
}

file2.swift:

import UIKit

class C: A{     
}

我正在阅读到公共类不能在模块外被子类化。这里我有一个子类C。我试图理解这里的模块是什么意思。我将UIKit导入到同一模块中的两个文件中。因此,这两个文件属于同一模块吗?以便我可以进行子类化。或者即使我导入相同的UIKit,这两个文件也具有不同的模块?

有人能解释一下什么是模块吗?

来源:

具有公共访问权限或任何更严格访问级别的类只能在定义它们的模块内进行子类化。

具有公共访问权限或任何更严格访问级别的类成员只能在定义它们的模块内被子类化。

2个回答

48
一个模块是代码分发的单个单位 - 一个框架或应用程序,作为单个单位构建和发送,并可以由Swift的import关键字导入另一个模块。在Xcode中,每个构建目标(例如应用程序包或框架)在Swift中被视为单独的模块。如果将应用程序代码的各个方面组合成一个独立的框架 - 可能是为了封装和重用跨多个应用程序的代码 - 那么在应用程序中导入并使用该框架时,以及在另一个框架中使用它时,该框架中定义的所有内容都将成为单独的模块的一部分。
文档所示,模块是应用程序或框架(库)。如果您创建了具有类A和B的项目,则它们是同一模块的一部分。同一项目中的任何其他类都可以从这些类继承。但是,如果将该项目导入到另一个项目中,则来自另一个项目的类将无法子类化A或B。为此,您必须在声明之前添加open指示符。
基本上,如果您只处理单个应用,则正在一个单个模块中工作,除非声明为private或fileprivate,否则类可以相互子类化。
编辑
让我们在模块(项目)Module1中拥有以下类:
class A {
}

由于这个类不是 open,所以只能在同一模块内进行子类化。也就是说,下面的类:

class B: A {
}

这段代码只能在同一个项目的Module1中编写。

如果你将Module1作为依赖添加到项目Module2中,并尝试执行以下操作:

import Module1

class C: A {
}

它不会编译。那是因为类A不是open(换句话说,它的访问权限为public或更低),并且它不属于与C相同的模块。A属于Module1,C属于Module2。
注意:import关键字将一个依赖模块导入到当前模块中。如果在项目中写入import UIKit,则告诉编译器您想在模块中使用UIKit模块。import不定义当前模块。当前模块是当前项目。
在文件开头添加import UIKit不会改变也不会定义文件所属的模块。它只是告诉编译器,您想在该文件中使用来自UIKit模块的代码。

@John,那里已经解释了,但我添加了一个例子来更好地解释它,请阅读更新后的答案。 - Milan Nosáľ
@John Playground和Storyboard是两个不同的模块。然而,我不确定playground是否可以包含一个storyboard。但是,一个项目中的storyboard和类属于同一个项目。 - Milan Nosáľ
非常感谢,现在我明白了。你能看一下这个文件吗?为什么Playground中有open class呢?https://files.fm/u/24xa2nhw - John
sources/cardController.swift 文件 - John
@John 我不知道为什么那是一个开放类.. 如果它在同一模块中被定义和实现,并且没有在其他地方使用,那么没有理由这样做.. 游乐场用于玩弄代码,而不是实现框架 - 因此我怀疑在任何游乐场代码中都没有使用 open 的任何理由。 - Milan Nosáľ
显示剩余4条评论

3

Swift模块(.swiftmodule)

历史:

[#include -> #import] -> [预编译头文件.pch] -> [@import Module(ObjC);] -> import Module(Swift)

有两种类型的模块 - 文件夹和文件

  • .swiftmodule 文件夹。该文件夹包含用于架构的所有.swiftmodule文件和其他元信息,例如:

    • .swiftmodule 文件。这是一种二进制文件格式,其中包含框架公共API的抽象语法树(AST)或Swift中间语言(SIL)。
    • .swiftdoc - 附加文档可供消费者查看
    • .swiftinterface - 模块稳定性

[.swiftinterface或Swift模块接口]是改善闭源兼容性的下一步

当您跳转到导入模块的定义时,实际上您正在审查.modulemap的公共接口

二进制文件(库、框架)可以包含多个模块,每个模块可以包含一种子模块(来自Objective-C世界)。

import struct SomeModule.SomeStruct

这些模块之间可以存在依赖关系。

  • 模块是一组解决同一问题的源代码文件,因此它们可以归为同一个模块名称下。
  • 模块帮助将源代码分组以便重复使用。
  • 模块有助于 Xcode 最小化构建时间 (开放源代码) (如果模块没有更改,则不应重新编译)。

此外,模块是一种范围,可帮助编译器确定要使用哪个类。如果两个模块使用相同的名称,则会出现

Ambiguous use of 'foo()'

可以通过以下方式解决:
import ModuleName1
import ModuleName2

func someFunc() {
    ModuleName1.SomeClass.foo()
    ModuleName2.SomeClass.foo()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接