swift封装_Swift中的封装,访问控制和框架

swift封装

As far as papers go, I must confess this is a little long at some 2,000+ words. In the first half, I cover three basic access types: private, file private, and internal. In the second half, I cover creating a framework with public and open access types. Both sections are labeled and can be read independently.

就论文而言,我必须承认这有点长,大约有2,000多个单词。 在上半年中,我将介绍三种基本的访问类型:私有,文件私有和内部。 在第二部分中,我将介绍创建具有公共和开放访问类型的框架。 这两个部分均已标记,可以独立阅读。

Let’s start with some background. Back in the bygone days of the 1970s, the professor of Informatics at ETH Zurich, Switzerland, a man called Niklaus Wirth created and published what was then a revolutionary language for teaching. A language he called Pascal. It was a language based on his book Algorithms + Data Structures = Programs.

让我们从一些背景开始。 早在1970年代,瑞士苏黎世联邦理工学院的信息学教授叫尼克劳斯·沃思 ( Niklaus Wirth),他创造并出版了当时的革命性教学语言。 他称为Pascal的语言。 这是一种基于他的书“ 算法+数据结构=程序”的语言

It was one of the first high-level computer languages to introduce the concept of encapsulation. A concept we all take for granted today. The principle idea within it, the need to create a scope within which access to elements in your code could be restricted. The idea of private and public variables and methods.

它是最早引入封装概念的高级计算机语言之一。 我们今天都认为这是理所当然的概念。 其中的基本思想是创建一个范围的需求,该范围可以限制对代码中元素的访问。 私有和公共变量和方法的思想。

Indeed Pascal as a language was so well designed that Apple decided to use it to write Mac OS. Mac OS as in the OS in which the fated Lisa and Macintosh computers ran. A brave decision at a time when everybody else was still using C.

实际上,Pascal作为一种语言的设计是如此出色,以至于Apple决定使用它来编写Mac OS。 Mac OS,如运气好的Lisa和Macintosh计算机的OS。 在其他所有人仍在使用C的时候做出了一个勇敢的决定。

In the meantime, C itself was undergoing a transformation. Ten years after the launch of Pascal with the development of Objective C, again a language that adopted the ideas and concept of encapsulation. Coincidentally a language picked up again by Steve Jobs's new team on the NextStep OS project. The company that would give us Objective C.

同时,C本身正在接受转换。 Pascal推出十年后,随着Objective C的发展,该语言再次采用了封装的思想和概念。 碰巧的是,史蒂夫·乔布斯(Steve Jobs)的新团队在NextStep OS项目中再次采用了一种语言。 给我们目标C的公司

The rest is history, as they say. Jobs returned to Apple in 1997, bringing with him a new OS and a new language, Objective C. Objective C as you know, the precursor to Swift, which as we all know came out in 2014.

正如他们所说,其余就是历史。 乔布斯于1997年返回苹果,带来了一个新的操作系统和一种新的语言,即ObjectiveC。众所周知,Objective C是Swift的前身,众所周知,Swift在2014年问世。

Today, Swift has continued to build on Pascal’s legacy and has five levels of encapsulation in the language: private, fileprivate, internal, public, and open. Levels of access can applied to variables, classes, structs, enums, functions, methods, and even the new wrappers build-out of SwiftUI. Levels of access that are relative to the source file the entities and/or modules that said code is defined within.

如今,Swift继续在Pascal的遗产基础上继续发展,并在语言上具有五个封装级别:私有,文件私有,内部,公共和开放。 访问级别可以应用于变量,类,结构,枚举,函数,方法,甚至可以应用于SwiftUI的新包装。 相对于源文件的访问级别,在源文件中定义了所述代码的实体和/或模块。

私有,FilePrivate和内部 (Private, FilePrivate, and Internal)

Ok enough history, let’s code. We’re going to use two projects to illustrate how these levels of access work. We begin with the most restrictive, private. Create a new project using SwiftUI as the interface and add a cocoa touch class file to it, call it Person.class, and add the code you see here.

好的历史记录,让我们编码。 我们将使用两个项目来说明这些访问级别的工作方式。 我们从限制性最强的隐私开始。 使用SwiftUI作为界面创建一个新项目,并向其中添加可可触摸类文件,将其命名为Person.class,然后添加您在此处看到的代码。

class Person {
var id: String = "SecretID"
}

The SwiftUI interface access this object needs to look like this.

该对象的SwiftUI接口访问应如下所示。

The default access level here is internal. Internal means accessible across the entire module in which they are defined. By default, everything you create in an Xcode project has internal access. So having named the Person class within the SwiftUI implementation, all the variables within it are accessible to it. Now let’s try to lock things down a little. Change the id in the person class to make it private.

此处的默认访问级别是内部。 内部方法可在定义它们的整个模块中访问。 默认情况下,您在Xcode项目中创建的所有内容都具有内部访问权限。 因此,在SwiftUI实现中命名了Person类后,即可访问其中的所有变量。 现在,让我们尝试锁定一些东西。 更改人员类别中的id以使其私有。

private var id: String = "SecretID"

You will immediately get an error in your ContentView.swift SwiftUI code to warn you the class variables are no longer accessible. We’ve broken it, how to fix.

您将在ContentView.swift SwiftUI代码中立即收到错误消息,以警告您不再可以访问类变量。 我们已经破解了,如何解决。

Now let’s assume we don’t want to change the id, we want to just read it. We can fix this error by defining a method within the class that we can use to return said id. Change the Person ID class to look like the code shown here.

现在假设我们不想更改id ,我们只想读取它。 我们可以通过在类中定义一个可用来返回所述ID的方法来解决此错误。 更改Person ID类,使其看起来像此处显示的代码。

class Person {
private var id: String = "SecretID"
func displayid() -> String {
return id
}
}

And well since the function displayed() will be assigned internal permissions, we can call said function within our SwiftUI code.

而且由于函数display displayed()将被分配内部权限,因此我们可以在SwiftUI代码中调用该函数。

struct ContentView: View {
@State var person = Person()
var body: some View {
Text("\(person.displayid())")
}
}

Moving forward imagine we need to be able to change the secret ID. To do that we can create a new class (although in the same file as the Person.class)to which will add a function shown here.

展望未来,我们需要能够更改secret ID 。 为此,我们可以创建一个新类(尽管与Person.class在同一文件中),在该类中添加此处显示的功能。

class Management {
static func updateID(for person:Person, with newID:String ) {
person.id = newID
}
}

Of course, your new Management class won’t have access to the person.id initially either, since it is a different class much like the SwiftUI struct. You will get the same error as you did before.

当然,新的Management类最初也将无法访问person.id ,因为它是一个与SwiftUI结构非常相似的类。 您将得到与以前相同的错误。

To fix this, but retain some security, we can change the access level of the id variable in our Person class to fileprivate. Since you defined the Management class in the same file as the Person class, it will gain access; without opening up access to the SwiftUI implementation in the ContentView.swift file.

要解决此问题,但要保留一些安全性,我们可以将Person类中id变量的访问级别更改为fileprivate 。 由于您在与Person类相同的文件中定义了Management类,因此它将获得访问权限; 而不在ContentView.swift文件中打开对SwiftUI实现的访问。

fileprivate var id: String = "SecretID"

You can test the new implementation by changing the ContentView.swift of your code to look like this.

您可以通过将代码的ContentView.swift更改为如下所示来测试新的实现。

This will update the ID you’ll see on the screen three seconds after it initially displays the secret ID message. Note, I needed the dnr variable here because without it SwiftUI will not know that it needs to re-run the main body again.

这将更新ID ,你会在屏幕三秒看到它最初显示后secret ID消息。 注意,我在这里需要dnr变量,因为没有它,SwiftUI不会知道它需要再次重新运行主体。

框架,公共和开放 (Frameworks, Public, and Open)

Now to illustrate the final two levels of encapsulation we’re going to switch projects. Go back to the desktop and create a new project. Call it BuyersPortal; I am going to use SwiftUI as an interface again.

现在,为了说明封装的最后两个级别,我们将切换项目。 返回桌面并创建一个新项目。 称为BuyersPortal; 我将再次使用SwiftUI作为接口。

Open the ContentView.swift and add these structures and classes to it.

打开ContentView.swift并向其中添加这些结构和类。

What we define here is a Product record and a class that will use it. Now update the ContentView.swift to access your new struct/classes.

我们在此处定义的是产品记录和将使用它的类。 现在更新ContentView.swift以访问您的新结构/类。

When you’re ready to run; go for it. It’ll display the newCustomer with a value of zero. Click on the text and it’ll access the method you just defined and the price will change. The default permissions on the Product and Purchases classes are internal and with everything in the same file, it’ll all work perfectly.

当您准备好跑步时; 去吧。 它将显示值为零的newCustomer 。 单击文本,它将访问您刚定义的方法,价格将发生变化。 ProductPurchases类的默认权限是内部权限,并且所有内容都在同一文件中,因此可以完美运行。

Now imagine you’re working with your peer, Stewart, remotely. Your part of the job is to define Product and Purchases objects and his part is to put it in action. Now you could write the code as you see here and ship the source, but it isn’t very practical and maybe you want to retain more control over it.

现在,假设您正在与同行Stewart远程合作。 您的工作部分是定义“ ProductPurchases对象,而他的部分是将其付诸实践。 现在,您可以按此处所见的方式编写代码并发送源代码,但这不是很实用,也许您想保留对其的更多控制权。

This is where frameworks, public, and open access controls come into the picture. You embed the Product and Purchases objects into a framework with public/open permissions. A framework you ship to Stewart confident that he’ll be able to use it, but not abuse it.

这是框架,公共和开放访问控制出现的地方。 您将“ Product和“ Purchases对象嵌入具有公共/开放权限的框架中。 您提供给Stewart的框架充满信心,他可以使用它,但不会滥用它。

To build a framework go back to Xcode and start a new project. Call it Engine, but wait, don’t choose the usual single page app, choose a framework this time.

要构建框架,请回到Xcode并开始一个新项目。 称它为Engine ,但是等等,不要选择通常的单页应用程序,这次选择一个框架。

Image for post
Screenshot by author.
作者截图。

A project will come up that will look rather bare with just a few files within it. Add a new swift source code file to it and copy and paste the code I outlined above defining the Product and Purchase objects & methods in your new framework project.

即将出现一个项目,其中仅包含几个文件就显得很裸露。 向其中添加一个新的快速源代码文件,然后将上面概述的代码复制并粘贴到新框架项目中,这些代码定义了ProductPurchase对象和方法。

Compile it and check that you haven’t made any typos and don’t have any errors. Close the project and now follow these steps carefully.

编译它,并检查您没有打错任何文字并且没有任何错误。 关闭该项目,然后现在仔细执行以下步骤。

  • Go back to the BuyersPortal project, the one with the code you just cut and pasted your struct and class out of, and comment everything out.

    返回到BuyersPortal项目,该项目带有刚刚剪切并粘贴结构和类的代码,并注释掉了所有内容。

  • Open the folder containing the Engine project (the one with the struct and class within in) and then drag the xcodeproj within it to the BuyersPortal.

    打开包含Engine项目的文件夹(其中包含struct和class的文件夹),然后将其中的xcodeproj拖到BuyersPortal

The file inspector of the BuyersPortal project should now look like this. The Engine project is within the BuyersPortal project.

现在, BuyersPortal项目的文件检查器应如下所示。 Engine项目在BuyersPortal项目中。

Image for post
Screenshot by author.
作者截图。

Strictly speaking, we didn’t need to include the whole Engine project here, we could just include the framework. But it makes more sense to include the whole project on this occasion since we’re going to be changing the code within it to get our permissions correct before we ship the framework to our man Stewart.

严格来说,我们不需要在这里包含整个Engine项目,我们可以仅包含框架。 但是在这种情况下包含整个项目更有意义,因为在将框架交付给我们的人Stewart之前,我们将更改其中的代码以获取正确的权限。

Now, compile everything to make sure we haven’t managed to corrupt our desktop. Ok, we’re ready to slowly rebuild the ContentView.swift in the BuyersPortal. Start with the line to define Purchases. It won’t work; you’ll get an error “Cannot find…”

现在,编译所有内容以确保我们没有破坏桌面。 好的,我们已经准备好在BuyersPortal缓慢重建ContentView.swif t了。 从定义“ Purchases的行开始。 它行不通; 您将收到错误消息“找不到...”

This isn’t a permission problem in swift, it is telling you it doesn’t know what you are talking about. It still an Xcode problem.

这不是快速的权限问题,它告诉您它不知道您在说什么。 它仍然是一个Xcode问题。

We need to do one more step to integrate our Engine project into the BuyersPortal. Go back to the project and expand the Engine project, look under products, you want the Engine.framework.

我们需要再做一步,将我们的Engine项目集成到BuyersPortal 。 返回该项目并展开Engine项目,在产品下面查找您想要的Engine.framework

Now select the BuyersPortal project and scroll down to the down to the Frameworks, Libraries, and Embedded Content area. You need to drag the Engine.framework you just found into this section. The BuyersPortal project Frameworks, Libraries, and Embedded Content should look like this if you get things correct.

现在选择BuyersPortal项目,然后向下滚动到Frameworks,Libraries和Embedded Content区域。 您需要将刚发现的Engine.framework拖到本部分中。 如果您正确无误,那么BuyersPortal项目的框架,库和嵌入式内容应如下所示。

Image for post
Screenshot by author.
作者截图。

Don’t make the mistake of dragging down to the Frameworks, Libraries, and Embedded code section of the Engine project, that won’t work!

不要误将其拖到Engine项目的Frameworks,Libraries和Embedded code部分,这是行不通的!

Having linked it in, make sure you now include it with an import statement in your ContentView.swift file too. The ContentView.swift in the BuyersPortal that is.

链接完之后,请确保现在也将它与导入语句一起包含在ContentView.swift文件中。 在BuyersPortal中的ContentView.swift

import Engine

Now uncomment the initial lines to define your first Purchases object.

现在取消注释初始行以定义您的第一个Purchases对象。

@State var newCustomer = Purchases()

It won’t work, but don’t worry, we’re almost there. Now you need to fix the Swift permissions.

这行不通,但是不用担心,我们快到了。 现在,您需要修复Swift权限。

At this point, all the permissions in the Engine class are set to the default ones, namely internal. Change the permission on the Purchases class to public and try again. The error message will change, it will now complain about the initializer not being public. Add an initializer to your Purchases class and compile it again. This time it’ll work. We’re making progress.

此时, Engine类中的所有权限都设置为默认权限,即内部权限。 将“ Purchases类的权限更改为“公开”,然后重试。 错误消息将更改,现在将抱怨初始化程序未公开。 在您的Purchases类中添加一个初始化器,然后再次编译它。 这次它将起作用。 我们正在进步。

Uncomment the onTapGesture to the Text object, it will complain again about the access rights on the Product struct and the products variable within the Purchases class, as well as access to the calculatePrice method. Make them all public in your Engine class. Your code in the Engine product should end up looking like this.

取消将onTapGesture注释为Text对象,它将再次抱怨对Product结构和Purchases类中的products变量的访问权限,以及对calculatePrice方法的访问。 将它们全部公开在您的Engine类中。 您在Engine产品中的代码应最终看起来像这样。

Compile and run. Tap on the newCustomer field and it should run the calculate price method and report a new price. And well, there you have it, public access.

编译并运行。 点击newCustomer字段,它将运行calculate price方法并报告新价格。 而且,您可以使用它,公共访问。

We covered all but the last type of access control, namely, open. Now imagine for a moment Stewart wants to subclass our Purchases class here. He might, for example, want a discount class. A class that inherits its values and methods directly from our Purchases class.

我们介绍了除最后一种访问控制(即开放)以外的所有内容。 现在想象一下,斯图尔特想在这里将我们的Purchases类归类。 例如,他可能想要折扣课程。 直接从我们的Purchases类继承其值和方法的类。

Edit the BuyersPortal project and add a new file to it, a DiscountPurchases.swift. Within the DiscountPurchases.swift file add this code. Stewart would like to offer discounts to buyers who are older than 55.

编辑BuyersPortal项目并向其中添加一个新文件DiscountPurchases.swift 。 在DiscountPurchases.swift文件中,添加此代码。 斯图尔特想为55岁以上的买家提供折扣。

To be clear, this won’t work yet. We need to tweak the permissions on our Engine class again.

需要明确的是,这还行不通。 我们需要再次调整Engine类的权限。

If he tried it as is, it will return another access control error. This isn’t what we want or what he needs. Change the code to look like this. You need to make the purchases class an open one. Change the public access on the function calculatePrice too, since he will also need access to this.

如果他按原样尝试,它将返回另一个访问控制错误。 这不是我们想要的,也不是他的需要。 更改代码看起来像这样。 您需要将purchases课程设为公开课程。 还要更改函数calculatePrice上的公共访问权限,因为他也将需要访问此权限。

open class Purchases {

Now go back again to the DiscountPurchases class and add this code.

现在,再次返回DiscountPurchases类,并添加此代码。

override func calculatePrice() -> Double {
super.calculatePrice() * (1 - discountPercentage / 100)
}

Everything should now compile. All you need to do is add some code into the SwiftUI field to bring it all together. To test your new framework that you’ll be shipping out, use this code.

现在一切都应该编译了。 您需要做的就是将一些代码添加到SwiftUI字段中,以将它们整合在一起。 要测试将要交付的新框架,请使用此代码。

Which brings me to the end. We’ve covered all the major access types in these two projects. Before I go, however, I want to point you in the direction of a video on which much of this paper is based. A video put together by, you guessed it, my peer Stewart. An excellent resource that covers the same material you’ll find here, going into a little more detail. You can find the video here.

这使我走到了尽头。 我们已经涵盖了这两个项目中的所有主要访问类型。 但是,在开始之前,我想向您介绍视频,该视频是本文的大部分内容。 您猜对了,我的同伴Stewart录制的视频。 一个很好的资源,涵盖了您将在此处找到的相同材料,并进行了更详细的介绍。 您可以在此处找到视频。

翻译自: https://medium.com/better-programming/encapsulation-access-controls-and-frameworks-in-swift-6b5ddf8ce717

swift封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值