Swift 中类似 Java 的注解:Attribute

前言

本文将描述 Java 中使用注解(annotation)的优势及原理(但是不会介绍 Java 注解的使用和自定义,你可以网上搜索相关资料),以及类似 Java 注解的 Swift Attribute,同时还会思考如果 Swift 支持自定义 Attribute 会有什么好处。

Java 使用注解的优势

举例来说,Java 的 Web 框架 SpringMVC,这个框架的核心思想之一是使用 Java 的注解来简化 Web 工程配置。只需很少的代码就可以构造一个 Restful API。如下所示(代码引用来自 Building a RESTful Web Service 官方 demo):

package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(),
                            String.format(template, name));
    }
}

这里简单的几句代码,就完成了一个 /greeting API 的所有编码及配置(当然,这里忽然了 Model 类)。

SpringMVC 的优势之一是避免了像 Struts2 一样要配置和维护 XML 文件。所以用户可以不在过问 XML 文件,使用纯 Java 语言来完成所有开发及配置。

Java 注解原理

Java 编译器在将源码编译成字节码的同时,会处理注解符号并附加到字节码的结构中。编译出来的文件大致包含类、类的方法、类的成员变量这三种信息,对于添加了注解的元素,编译器会同时在相应的元素上添加注解信息。

当 JVM 开始加载字节码文件的时候,会去读取类、类的方法、类的成员变量这些信息,当发现读取的信息中包含注解信息的时候则去处理这些信息。对待注解信息的逻辑有两种,一个是类加载完成以后丢弃,一个是类加载完成以后不丢弃。当然在编译阶段编译器也可以处理注解信息,根据注解信息对用户输出编译警告或者错误,所以注解的处理逻辑事实上有三种。

从这里我们可以发现注解的实现实际上需要两种支持:

  1. 编译器的支持。这样我们才能将注解信息加入到编译输出的文件(对 Java 来说是字节码,对 c/c++/objC 来说是 object 文件)
  2. 类加载支持。根据编译输出的文件结构加载类的时候,同时读取注解信息,根据注解信息进行相应的处理

Swift 的注解: Attribute

事实上很多其他语言也有类似 Java 注解的这种东西,比如 c# 和 Swift 的 Attribute。

Swift 的 Attribute 使用在 Swift 的开发中其实也是非常普遍的,比如下面这个 AppDelegate:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        return true
    }
}

通过使用 @UIApplicationMain 编译器就会知道下面的 AppDelegate 这个类就是 app 启动的时候系统需要调用的 app 代理。联想一下 ObjC 中我们是这样使用 AppDelegate

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

所以在相应的类定义前面使用 @UIApplicationMain,我们就不需要自己告诉 iOS 系统该 app 的代理是哪个类。
并且如果你定义的 AppDelegate 没有实现 UIApplicationDelegate 的话,编译器在编译阶段就会展示一个编译错误给你,提示你应该去实现这个协议。

Swift Attribute 的使用及缺点

Swift 语言本身定义了很多 Attribute 给开发人员使用,你可以查看官方文档了解使用详情。

网上有人也整理了一份 Swift 的所有 Attribute 以及说明,swift attributes 符号,当然随着 Swift 的发展可能会有越来越多的 Attribute 加入,原有的 attribute 也可能有些变化。

目前 Swift Attribute 的缺点是无法支持自定义,也就是说我们无法像 Java 一样使用注解。官方提供的 Attribute 的效果非常有限。有可能随着 Swift 的发展后面会加入对自定义 Attribute 的支持,毕竟 Swift 本身是已经支持 Attribute 的。关于 Swift 支持自定义 Attribute 你可以看 Swift 关于自定义 Attribute 实现的讨论

如果 Swift 支持自定义 Attribute

让我们来想一想如果 Swift 可以支持自定义注解的话有什么好的? Medium 上面有人已经这样设想了,你可以看 Custom Attributes in Swift Language 来了解。

但是对我来说,Swift 自定义 Attribute 的最大一个好处是,会出现类似 SpringMVC 这样的框架,用于支持 Swift 的后端开发,以及革新移动端开发方式。

一方面,很多人开始将 Swift 用于后端开发,类似 SpringMVC 这样的 Swift Web 框架也一定会出现。

另一方面,现在很多移动端开始支持 Router,也就是移动 app 里面页面的跳转是基于 URL 的,这样的开源代码很多比如 JLRoutes,但是基于 URL 的跳转的缺陷是需要配置 URL 跳转逻辑。我们是否可以想象一下,移动端的开发以后也可以像上面我举例的 SpringMVC demo 一样,通过简单的使用注解,当一个 URL 请求来的时候新的框架能够自动帮我们解析,并跳转到该界面,省去了配置 URL 和解析 URL?

总结

Java 注解的使用可以简化项目的配置,因为编译器和类加载机制可以根据注解来帮助我们完成这一部分配置,使得开发人员可以专注于语言本身。

另一方法 Swift 的 Attribute 作用则非常有限,但是由于 Swift 本身是支持 Attribute 的,如果未来 Swift 能支持自定义 Attribute 的话,想象空间还是很大的。

引用

  1. Building a RESTful Web Service
  2. Swfit 语言官方文档 - Attribute
  3. Swift 关于自定义 Attribute 实现的讨论
  4. Java 注解机制及其原理
  5. Java中的注解是如何工作的?
  6. 深入理解 Swift 派发机制
  7. swift attributes 符号
  8. Custom Attributes in Swift Language
  9. SpringMVC
  10. JLRoutes

2018年3月3日 更新

最近在了解 Javascript 的原型,以及 ES2016 等标准。发现 Javascript 里面也有类似 Java 的 @ 符号开始的注解,不过 Javascript 里面把它叫做修饰器。原理就是用一个 @ 符号标注开始的函数去修饰另外一个函数。这种方式很让我受启发,本质上 Swift 的 extension 就是一种对类、接口等的修饰(或者是 Objective C 的 category)。或许借助 extension 能够实现类似注解的效果?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,618评论 4 59
  • 2010年在美国,在保研和工作之间我战战兢兢地选择了后者,也是在那个大西洋的海岸边有了我人生的第一个五年计划。...
    f794b260adc7阅读 99评论 0 0
  • 在林心如和霍建华结婚,她的婚前写真刷屏的这一天,我却失恋了。 在我和他讨论正式分手的时候,我正在和全家族...
    花间集阅读 245评论 0 0
  • 当某一个群体,超过三个人以上。就会产生这种奇怪的组织。私下里来往密切,公开场合也谈笑风生,甚至故意制造一些动静,让...
    山间农夫阅读 206评论 0 0