[译] 思考实践:用 Go 实现 Flutter,字节跳动Android岗面试题

         ),
        Text(
          '$_counter',
          style: Theme.of(context).textTheme.display1,
        ),
      ],
    ),
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: _incrementCounter,
    tooltip: 'Increment',
    child: Icon(Icons.add),
  ),
);

}
}


我们先把它分解成几个部分,分析哪些可以映射到 Go 中,哪些不能映射,并探索目前我们拥有的选项。

### 映射到 Go

一开始是相对比较简单的 —— 导入依赖项并启动 `main()` 函数。这里没有什么挑战性也不太有意思,只是语法上的变化:

package hello

import “github.com/flutter/flutter”

func main() {
app := NewApp()
flutter.Run(app)
}


唯一的不同的是不使用魔法的 `MyApp()` 函数,它是一个构造方法,也是一个特殊的函数,它隐藏在被称为 `MyApp` 的类中,我们只是调用一个显示定义的 `NewApp()` 函数 —— 它做了同样的事情,但它更易于阅读、理解和弄懂。

### Widget 类

在 Flutter 中,一切皆 widget(小组件)。在 Flutter 的 Dart 版本中,每个小组件都代表一个类,这个类扩展了 Flutter 中特殊的 Widget 类。

Go 中没有类,因此也没有类层次,因为 Go 的世界不是面向对象的,更不必说类层次了。对于只熟悉基于类的 OOP 的人来说,这可能是一个不太好的情况,但也不尽然。这个世界是一个巨大的相互关联的事物和关系图谱。它不是混沌的,可也不是完全的结构化,并且尝试将所有内容都放入类层次结构中可能会导致代码难以维护,到目前为止,世界上的大多数代码库都是这样子。

![OOP 的真相](https://user-gold-cdn.xitu.io/2019/7/7/16bca4d08789c000?imageView2/0/w/1280/h/960/ignore-error/1)

我喜欢 Go 的设计者们努力重新思考这个无处不在的基于 OOP 思维,并提出了与之不同的 OOP 概念,这与 OOP 的发明者 Alan Kay 所要表达的[真实意义]( )更接近,这不是偶然。

在 Go 中,我们用一个具体的类型 —— 一个结构体来表示这种抽象:

type MyApp struct {
// …
}


在一个 Flutter 的 Dart 版本中,`MyApp`必须继承于 `StatelessWidget` 类并覆盖它的 `build` 方法,这样做有两个作用:

1.  自动地给予 `MyApp` 一些 widget 属性/方法
2.  通过调用 `build`,允许 Flutter 在其构建/渲染管道中使用跟我们的组件

我不知道 Flutter 的内部原理,所以让我们不要怀疑我们是否能用 Go 实现它。为此,我们只有一个选择 —— [类型嵌入]( )

type MyApp struct {
flutter.Core
// …
}


这将增加 `flutter.Core` 中所有导出的属性和方法到我们的 `MyApp` 中。我将它称为 `Core` 而不是 `Widget`,因为嵌入的这种类型还不能使我们的 `MyApp` 称为一个 widget,而且,这是我在 [Vecty]( ) GopherJS 框架中看到的类似场景的选择。稍后我将简要的探讨 Flutter 和 Vecty 之间的相似之处。

第二部分 —— Flutter 引擎中的 `build` 方法 —— 当然应该简单的通过添加方法来实现,满足在 Go 版本的 Flutter 中定义的一些接口:

flutter.go 文件:

type Widget interface {
Build(ctx BuildContext) Widget
}


我们的 main.go 文件:

type MyApp struct {
flutter.Core
// …
}

// 构建渲染 MyApp 组件。实现 Widget 的接口
func (m *MyApp) Build(ctx flutter.BuildContext) flutter.Widget {
return flutter.MaterialApp()
}


我们可能会注意到这里和 Dart 版的 Flutter 有些不同:

*   代码更加冗长 —— `BuildContext`,`Widget` 和 `MaterialApp` 等方法前都明显地提到了 `flutter`。
*   代码更简洁 —— 没有 `extends Widget` 或者 `@override` 子句。
*   Build 方法是大写开头的,因为在 Go 中它的意思是“公共”可见性。在 Dart 中,大写开头小写开头都可以,但是要使属性或方法“私有化”,名称需要使用下划线(\_)开头。

为了实现一个 Go 版的 Flutter `Widget`,现在我们需要嵌入 `flutter.Core` 并实现 `flutter.Widget` 接口。好了,非常清楚了,我们继续往下实现。

状态
--

在 Dart 版的 Flutter 中,这是我发现的第一个令人困惑的地方。Flutter 中有两种组件 —— `StatelessWidget` 和 `StatefulWidget`。嗯,对我来说,无状态组件只是一个没有状态的组件,所以,为什么这里要创建一个新的类呢?好吧,我也能接受。但是你不能仅仅以相同的方式扩展 `StatefulWidget`,你应该执行以下神奇的操作(安装了 Flutter 插件的 IDE 都可以做到,但这不是重点):

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
int _counter = 0;

void _incrementCounter() { <

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值