前言
Flr 是我主导的和组织团队对外开源的第一款作品——一个用于帮助管理Flutter资源的开发工具系列产品,包括:
- flr-as-plugin:
Flr
的Android Studio插件版本 - flr-vscode-extension:
Flr
的VSCode插件版本 - flr-cli:
Flr
的命令行版本
在这里,主要分享一下Flr
背后的产品观和开发观。
Flr 是我主导的和组织团队对外开源的第一款作品——一个用于帮助管理Flutter资源的开发工具系列产品,包括:
Flr
的Android Studio插件版本Flr
的VSCode插件版本Flr
的命令行版本在这里,主要分享一下Flr
背后的产品观和开发观。
这是一道从此篇博客《神经病院 Objective-C Runtime 入院第一天—— isa 和 Class》看到的题目:
问:下面代码输出什么?
1
2
3
4
5
6
7
8
9
10
11
12 @implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
答案是: 输出的都是Son
。
对此,博客作者给出的理由是:
self和super的区别:
self是类的一个隐藏参数,每个方法的实现的第一个参数即为self。
super并不是隐藏参数,它实际上只是一个”编译器标示符”,它负责告诉编译器,当调用方法时,去调用父类的方法,而不是本类中的方法。
在调用[super class]的时候,runtime会去调用objc_msgSendSuper方法,而不是objc_msgSend
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained Class class;
#else
__unsafe_unretained Class super_class;
#endif
/* super_class is the first class to search */
};在objc_msgSendSuper方法中,第一个参数是一个objc_super的结构体,这个结构体里面有两个变量,一个是接收消息的receiver,一个是
当前类的父类super_class。入院考试第一题错误的原因就在这里,误认为[super class]是调用的[super_class class]。
objc_msgSendSuper的工作原理应该是这样的:
从objc_super结构体指向的superClass父类的方法列表开始查找selector,找到后以objc->receiver去调用父类的这个selector。注意,最后的调用者是objc->receiver,而不是super_class!那么objc_msgSendSuper最后就转变成
1
2
3
4
5
6
7
8
9
10
11 // 注意这里是从父类开始msgSend,而不是从本类开始,谢谢@Josscii 和他同事共同指点出此处描述的不妥。
objc_msgSend(objc_super->receiver, @selector(class))
/// Specifies an instance of a class. 这是类的一个实例
__unsafe_unretained id receiver;
// 由于是实例调用,所以是减号方法
- (Class)class {
return object_getClass(self);
}由于找到了父类NSObject里面的class方法的IMP,又因为传入的入参objc_super->receiver = self。self就是son,调用class,所以父类的方法class执行IMP之后,输出还是son,最后输出两个都一样,都是输出son。
其实,上述的解答只答对了一大半,还有一小半没正确。没正确的部分主要在于对objc_msgSend
和objc_msgSendSuper
的工作原理理解错误,以及对方法实现的函数原型的忽略。
下面将会对此进行重新解答。
在面向对象领域中,方法(method)和函数(function)有什么区别和关联呢?
在面向对象领域中,方法和函数的区别是:
定义不一样
与对象的关系不一样
传递的数据(比如参数)不一样
可访问范围不一样
为何重启个人博客?
这个问题很早就想发文表达了,如今时机终于到了——在这个人博客重建完毕的时候,可以好好的来对此说说了。
重启个人博客的念头源自18年8月简书创作平台发的一则公告:
翻阅《网络安全法》,并没有出现要求绑定“微信”的明文要求,而行业内,“网络运营者”(使用国法里的称法)的常规做法也只是要求用户绑定手机号即可——很明显地,简书这是在假借国法,浑水摸鱼,愚弄用户。
坦白而言,简书是我很喜欢的一个写作平台,它的优秀写作体验,甚至让我做了停止搭建个人博客,专注于写作本身的决定——这在当时的简书个人介绍上可见一斑:
然而,甚是没想到简书对用户如此毫无尊重和敬畏,所以在那之后,决定了迁移到掘金上进行写作。
那,既然已经有另一个平台供写作了,为何还是要重启个人博客呢?
为何“要”呢?
人生来之时是善还是恶,这无法定论。但是,人生来之后,却无法保证自身不作恶。平台是人搭建的,自是平台也无法保证自身不作恶。所以必须重启个人博客,对自己的文章进行备份,以在所寄身的写作平台在作恶之时,有路可退。
为什么Objective-C中有Class和MetaClass这种设计?
这个问题某日在掘金上看到的。我认为这不是一个技术领域的问题,而是编程语言的设计选择领域的问题。
在Objective-C编程语言的设计中,类(Class)既是一个用于描述对象实例(object)的属性和行为的工具,也是一个对象(Object),有自身的属性和行为;那类(Class)的属性和行为使用什么来描述呢?答案就是:元类(MetaClass)。只不过元类(MetaClass)处于编程语言的实现底层,对开发者是透明的。
那取消掉元类(MetaClass)可以吗?
答案是:可以。但是这需要从该编程语言的设计上做根本的调整:取消掉“类(Class)也是对象(Object)”的设计,把类(Class)同时当作描述对象实例(object)和类(Class)自身的属性和行为的工具。采用与此类似的设计的编程语言也存在,比如C++。
在产品层面上,Windows与Unix/Linux的区别主要体现在二者服务的对象和应用场景上:
在人机关联层面上,,Windows与Unix/Linux的区别主要体现在二者与人和机器的关联程度上:
在桌面系统层面上,Windows是一个桌面系统,Unix/Linux则不是一个桌面系统。
为减少手写实现JSON和模型类相互转换的序列化、反序列化代码,我们使用了官方推荐的json_serializable方案。
同时为了解决json_serializable
方案需要手动写为模型类写from/to json
的代码的问题,我们引入了代码片段的解决方案。
下面将会对该方案进行具体描述。
- 该方案同时适用于VSCode和Android Studio;
- 下文在描述该方案时,只介绍了VSCode端的实施步骤;
- 在Android Studio落地该方案时,只需要把涉及VSCode端的实施对等转换为Android Studio端的实施即可:比如“为VSCode添加代码片段”转换为“为Android Studio添加代码片段”。