• relax 置顶
    2019-08-14
    能不能所有的示例代码放到一个git下面

    作者回复: 代码还是要分开放的,因为每节分享都是独立的一个可运行工程,不只是代码,还有CI和单测一堆工程相关的东西,集中放就没法管理了。
    我单起了一个仓库,用submodule的方式把这些demo都收进去了,可以自取
    https://github.com/cyndibaby905/flutter_core_demo

    
     1
  • Ω
    2019-07-16
    Item operator+(Item item) => I...
    double get price => bookings...

    这个改造+号的代码还是无法看懂

    作者回复: operator+:把两个Item对象合并为一个。新Item对象的name为这两个对象的name拼接而成,price为他们的price相加而成。

    get price:对列表数据采用累加的方式进行求和。这里用到了reduce方法。reduce是函数迭代方法,需要传递一个二元函数进行列表的合并工作。list[0...n].reduce(f)等于:
    a0 = list[0]
    a1 = f(a0,list[1])
    a2 = f(a1,list[2])
    an = f(an-1,list[n])
    在这里我们的f是求和函数f(x,y)=x+y,可以理解成an=list[0]+list[1]+list[n-1]+list[n]

     1
     22
  • bytecode
    2019-07-16
    double get price() {
      double sum = 0.0;
      for(var i in bookings) {
        sum += i.price;
      }
      return sum;
    }

    文中这里的price()是多了括号(),要去掉()
    展开

    作者回复: 感谢提醒

    
     10
  • jia58960
    2019-07-24
    大概能看懂并实现代码,但构造函数中的属性什么时候用this.属性,什么时候不用this,希望老师能回答下。

    作者回复: 类的实例变量:1.是声明时定义的,可以用this语法糖赋值;2.是继承来的,不能用this,需要把这个值交给super让父类赋值

    
     6
  • 江宁彭于晏
    2019-07-19
    class Meta {
      double price;
      String name;
      // 成员变量初始化语法糖
      Meta(this.name, this.price);
    }

    class Item extends Meta{
      Item(name, price) : super(name, price);
      // 重载 + 运算符,将商品对象合并为套餐商品
      Item operator+(Item item) => Item(name + item.name, price + item.price);
    }

    class Items {
      Item item;
      double num;
      Items(this.item, this.num);
      double get totalPrice => item.price * num;
    }

    abstract class PrintHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    //with 表示以非继承的方式复用了另一个类的成员变量及函数
    class ShoppingCart extends Meta with PrintHelper{
      DateTime date;
      String code;
      List<Items> bookings;
      // 以归纳合并方式求和
      double get shopPrice {
         double result = 0.0;
         bookings.forEach((element) => result+=element.totalPrice);
         return result;
      }

      // 默认初始化函数,转发至 withCode 函数
      ShoppingCart({name}) : this.withCode(name:name, code:null);
      //withCode 初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
      ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);

      //?? 运算符表示为 code 不为 null,则用原值,否则使用默认值 " 没有 "
      @override
      String getInfo() {
      String bookingsResult = '商品明细: \n';
      bookings.forEach((item) => bookingsResult += ' 商品名称:${item.item.name} 单价:${item.item.price} 数量 :${item.num} 总价:${item.totalPrice}\n');

      return '''
    购物车信息:
    -----------------------------
      用户名: $name
      优惠码: ${code??" 没有 "}
      $bookingsResult
      总价: $shopPrice
      Date: $date
    -----------------------------
    ''';
      }
    }

    void main() {
      ShoppingCart.withCode(name:'张三', code:'123456')
      ..bookings = [Items(Item('苹果',10.0),5.0), Items(Item('鸭梨',20.0),10.0)]
      ..printInfo();

      ShoppingCart(name:'李四')
      ..bookings = [Items(Item('香蕉',15.0),10.0), Items(Item('西瓜',40.0),1.0)]
      ..printInfo();
    }
    展开

    作者回复: 赞👍

    不过数量作为Item的属性会更好一点。

    
     3
  • Paradise
    2019-07-16
    这种结合代码的方式很友好,可以一边听一边上手,更容易理解...😀
    
     3
  • Carlo
    2019-10-15
    看到一段代码:
    firebaseService.login().then(
                            (value) {
                              print(value.toJson());
                            },
                            onError: (err) {
                              print(err);
                            },
                          );

    请问这个onError是怎么回事啊。为什么会被执行呢? 这是dart特有的语法么?
    我所知道的一般sync function的语法是

    thisFunction()
        .catch(console.error)
        .then(() => console.log('We do cleanup here'));
    展开

    作者回复: 给你展开一下你就明白了:
    funcThatThrows()
      .then(successCallback, onError: (e) {
        handleError(e); // Original error.
        anotherFuncThatThrows(); // new error.
      })
      .catchError(handleError); // Error from within then() handled.

    
     1
  • Uncle.Wang
    2019-08-20
    class Meta {
      double price;
      String name;
      // 成员变量初始化语法糖
      Meta(this.name, this.price);
    }

    abstract class PrintHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    class Item extends Meta with PrintHelper {
      int count;
      Item(name, price, {int count = 1}): super(name, price) {
        this.count = count;
      }
      // 重载 + 运算符,将商品对象合并为套餐商品
      Item operator+(Item item) => Item(name + item.name, price + item.price);
        @override
      getInfo() => '''
        商品名: $name
        单价: $price
        数量: $count
        ---------------
    ''';
    }

    //with 表示以非继承的方式复用了另一个类的成员变量及函数
    class ShoppingCart extends Meta with PrintHelper{
      DateTime date;
      String code;
      List<Item> bookings;
      // 以归纳合并方式求和
      double get price => bookings.reduce((value, element) => value + element).price;
      // 默认初始化函数,转发至 withCode 函数
      ShoppingCart({name}) : this.withCode(name:name, code:null);
      //withCode 初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
      ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);

      getBookingInfo() {
        String str = "";
        for (Item item in bookings) {
          str += item.getInfo();
        }
        return str;
      }

      //?? 运算符表示为 code 不为 null,则用原值,否则使用默认值 " 没有 "
      @override
      getInfo() => '''
    购物车信息:
    -----------------------------
      用户名: $name
      优惠码: ${code??" 没有 "}
      总价: $price
      Date: $date
      商品列表:
        ---------------
    ${ getBookingInfo() }
    -----------------------------
    ''';
    }

    void main() {
      ShoppingCart.withCode(name:'张三', code:'123456')
      ..bookings = [Item('苹果',10.0, count: 10), Item('鸭梨',20.0, count: 5)]
      ..printInfo();

      ShoppingCart(name:'李四')
      ..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
      ..printInfo();
    }
    展开

    作者回复: 非常棒!

    
     1
  • 和小胖
    2019-08-14
    老师您的第二个题目,我理解是要做每一种商品的分类,但是我还是用了以前语言的思路来做了。麻烦老师,看看是否正确。

    关键代码如下:
    //定义购物车类
    class ShoppingCar extends Meta with PrintHelper {
      DateTime date; //购物日期
      String code; //优惠券
      List<Item> _bookings; //定义私有属性
      num count; //商品数量

      //求出总价
      double get price =>
          books.reduce((value, element) => value + element).price;

      List<Item> get books => _bookings;

      //给bookings定义set方法
      set book(List<Item> bookings) {
        this._bookings = bookings;
        this.count = bookings.length;
      }

      //获取分类产品信息
      String getGoodsInfo() {
        StringBuffer temp = new StringBuffer();
        Map map = new Map<String, List<Item>>();
        books.forEach((item) {
          if (!map.containsKey(item.name)) {
            List list = new List<Item>();
            list.add(item);
            map[item.name] = list;
          } else {
            (map[item.name] as List<Item>).add(item);
          }
        });
        map.forEach((k, v) {
          temp.write("商品名称:$k,该种商品数量:${(v as List).length},该种商品单价:${(v as List<Item>)[0].price}元\n");
          print("$k,$v");
        });
        return temp.toString();
      }

      //这种表达式赋值还是挺方便的
      ShoppingCar.withCode({name, this.code}): this.date = DateTime.now(),super(name, 0.0);

      ShoppingCar({name}) : this.withCode(name: name, code: null);

      @override
      getInfo() {
        return '''
          购物车信息:
          ----------------------
          用户名:$name
          优惠码:${code ?? "没有优惠券啊"}
          商品总量:$count
          总价:$price
          日期:$date
          ${getGoodsInfo()}
          ----------------------
      ''';
      }
    }

    运行后信息如下:购物车信息:
          ----------------------
          用户名:小李
          优惠码:没有优惠券啊
          商品总量:3
          总价:29.0
          日期:2019-08-14 22:01:24.437085
          商品名称:苹果,该种商品数量:2,该种商品单价:10.0元
          商品名称:梨,该种商品数量:1,该种商品单价:9.0元
          ----------------------
    展开

    作者回复: 结果倒是对,但是这个购物车与我们理解的购物车还是有差异:
    1.count属性应该是Item对象的:一个Item对象有count个,而不是一直往购物车内加同样的对象count次;
    2.由于你的count属性无法拆分到Item类,导致getGoodsInfo的计算异常繁琐了。如果count属性在Item类,getGoodsInfo计算可以收敛到Item对象类内部。

    
     1
  • 刘荣清
    2019-08-03
    在vs code已经安装dart、code runner插件,本地也安装完dart SDK,然后通过vs code运行dart 提示:dart : 无法将“dart”项识别为 cmdlet、函数...
    但在cmd 控制板中就可以正常运行,这是为咋啊,vs code需要额外配置咋吗

    作者回复: 把dart命令所在的目录设置成环境变量PATH

    
     1
  • 灰灰
    2019-07-27
    abstract class PrintHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    class Meta {
      double price;
      String name;
      Meta(this.name, this.price);
    }

    // 定义商品Item类
    class Item extends Meta {
      int count;
      Item(name, price, this.count): super(name, price);
      Item operator+(Item item) => Item(name + item.name, price * count + (item.price * item.count), 1);
    }

    //定义购物车类
    class ShoppingCart extends Meta with PrintHelper {
      DateTime date;
      String code;
      List<Item> bookings;

      double get price => bookings.reduce((value, element) => (value + element)).price;
    // ShoppingCart(name, this.code): date = DateTime.now(), super(name,0);
      ShoppingCart({name}): this.withCode(name: name, code: null);
      ShoppingCart.withCode({name, this.code}): date = DateTime.now(), super(name, 0);
      getInfo () => '''
         购物车信息:
         
         ----------------
         商品名 单价 数量 总价
         ----------------
         ${bookings.map((item) => '${item.name} ${item.price} ${item.count} ${item.price * item.count}').join('\n ')}
         
         ================
         用户名: $name
         优惠码: ${code ?? "没有"}
         总价: $price
         日期: $date
      ''';
    }

    void main() {
      ShoppingCart.withCode(name: '张三', code: '123456')
      ..bookings = [Item('苹果', 10.0, 3), Item('鸭梨', 20.0, 1)]
      ..printInfo();

      ShoppingCart(name: '李四')
      ..bookings = [Item('香蕉', 2.4, 2), Item('芒果', 6.8, 4)]
      ..printInfo();
    }
    展开

    作者回复: 赞

    
     1
  • jianwei
    2020-01-07
    ```
    abstract class PrintHelper {
      printItemInfo() => print(getInfo());
      getInfo();
    }

    class Meta {
      double price;
      String name;
      int count;
      Meta(this.name, this.price, this.count);
    }

    // 定义商品类
    class Item extends Meta {
      // 商品名称、商品价格、商品数量
      Item(name, price, count) : super(name, price, count);

      Item operator+(Item item) => Item(name + item.name, price + item.price, count + item.count);
    }

    // 定义购物车类
    class ShoppingCart extends Meta with PrintHelper {
      DateTime date;
      String code;
      List<Item> bookings;

      // 计算总价格
      double get price {
        double totalPrice = 0;
        bookings.forEach((item)=> totalPrice += (item.price * item.count));
        return totalPrice;
      }
      // 计算商品总数量
      int get count => bookings.reduce((cur, next) => cur + next).count;

      // 构造函数
      ShoppingCart({name}) : this.withCode(name: name, code: null);
      ShoppingCart.withCode({name, this.code, count}) : date = DateTime.now(), super(name, 0, 0);

      // 打印信息

      getInfo() {
        String bookingsResult = "商品详情\n";
        bookings.forEach((item) => bookingsResult += '商品名:${item.name} 商品单价:${item.price} 商品数量:${item.count} \n');

        return '''
        购物车信息:
        -----------------------------
        用户名: $name
        优惠码: ${code??"没有"}
        商品详情: $bookingsResult
        总价: $price
        总数量: $count
        Date: $date
        -----------------------------
        ''';
      }
    }
    ```
    展开
    
    
  • 加温后的啤酒
    2019-12-23
    直接通过mixin关键字定义PrintHelper也比较简单:
    mixin PrintHelper {
      void printInfo() => print(getInfo());
      String getInfo();
    }

    展开

    作者回复: 赞

    
    
  • 庆
    2019-12-23

    class Meta {
      double price;
      String name;
      //成员变量初始化语法糖
      Meta(this.name, this.price);
    }

    class Item extends Meta{
      Item(name, price) : super(name, price);
      //重载+运算符,将商品对象合并为套餐商品
      Item operator+(Item item) => Item(name + item.name, price + item.price);
    }

    abstract class PrintHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    //with表示以非继承的方式复用了另一个类的成员变量及函数
    class ShoppingCart extends Meta with PrintHelper{
      DateTime date;
      String code;
      List<Item> bookings;
      //以归纳合并方式求和
      double get price => bookings.reduce((value, element) => value + element).price;
      //默认初始化函数,转发至withCode函数
      ShoppingCart({name}) : this.withCode(name:name, code:null);
      //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
      ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);

      //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
      @override
      getInfo() => '''
    购物车信息:
    -----------------------------
      用户名: $name
      优惠码: ${code??"没有"}
      总价: $price
      Date: $date
      物品数量: ${bookings.length}
    ''';

    printDetails(){
       bookings.forEach((item){
         print("物品 "+item.name + " 价格 ${item.price}");
       });

       print("-----------------------------");

    }

    }

    void main() {
      ShoppingCart.withCode(name:'张三', code:'123456')
      ..bookings = [Item('苹果',10.0), Item('鸭梨',20.0)]
      ..printInfo()
      ..printDetails();

      ShoppingCart(name:'李四')
      ..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
      ..printInfo()
      ..printDetails();
    }
    展开

    作者回复: 你这段代码没计算数量啊

    
    
  • DERUWE
    2019-12-09
    使用了这个Item operator+(Item item) => Item(name + item.name, price + item.price);最后的bookings就变为长度为1的吗

    作者回复: 这只是一个加号运算符,最后bookings变为1还需要使用reduce来做迭代累计额

    
    
  • 信仰年轻
    2019-11-22
    操作符重载,在kotlin c++里面都有的,用法跟dart一模一样啊
    
    
  • icer
    2019-11-19
    class Meta {
      double price;
      String name;
      Meta(this.name,this.price);
    }

    class Item2 extends Meta {
      int num;
      Item2(String name, double price,{this.num=1}) :super(name, price);
      Item2 operator + (Item2 item) => Item2(name + item.name,price * num + item.price * item.num);
    }

    abstract class printHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    class ShoppingCart2 extends Meta with printHelper {
      DateTime date;
      String code;
      List<Item2> bookings;

      ShoppingCart2({name}) : this.withCode(name:name,code:null);
      ShoppingCart2.withCode({name,this.code}) : date = DateTime.now(),super(name, 0);

      double get price => bookings.reduce((value,element) => value + element).price;

      String get cardInfo {
        String str = "";
        bookings.forEach((v) =>
        str +='${v.name} ----- ${v.num}\n');
        return str;
      }

      getInfo() {
        return
              """
            购物车信息:
            -----------------------------
            用户名: $name
            优惠码: ${code??"没有"}
            $cardInfo
            总价: $price
            日期: $date
            -----------------------------
            """;
      }
    展开

    作者回复: 赞👍

    
    
  • 一个工匠
    2019-11-12
    666
    
    
  • 入夜、渐微凉
    2019-11-07
    在一个道友的回答上稍加改动,加了一个商品总数和购物车为空的情况,老师帮忙看看有没有可以优化的地方。
    class Meta {
      double price;
      String name;
      String info;
      //成员变量初始化语法糖
      Meta(this.name, this.price);
    }
    class Item extends Meta {
      int count;
      Item(name, price, {int count = 1}) : super(name, price) {
        this.count = count;
        this.info = '''
     商品名: $name
       单价: $price
       数量: $count
       ---------------
      ''';
      }
      
      Item operator +(Item item) =>
          Item(name + item.name, price + item.price, count: count + item.count);
    }

    abstract class PrintHelper {
      printInfo() => print(getInfo());
      getInfo();
    }

    //with表示以非继承的方式复用了另一个类的成员变量及函数
    class ShoppingCart extends Meta with PrintHelper {
      DateTime date;
      String code;
      List<Item> bookings;
      //以归纳合并方式求和
      double get price =>bookings != null ?
          bookings.reduce((value, element) => value + element).price : 0.00;
      int get count => bookings != null ? bookings.reduce((value, element) => value + element).count : 0;
      //默认初始化函数,转发至withCode函数
      ShoppingCart({name, List<Item> bookings})
          : this.withCode(name: name, code: null, bookings: bookings);
      //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
      ShoppingCart.withCode({name, this.code, this.bookings})
          : date = DateTime.now(),
            super(name, 0) {
            if (bookings != null) {
                String str = "";
                for (Item item in bookings) {
                  str += item.info;
                }
                info = str;
            }
      }

      //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
      @override
      getInfo() => '''
    购物车信息:
    -----------------------------
      用户名: $name
      优惠码: ${code ?? "没有"}
      商品总数: $count
      总价: $price
      Date: $date
      商品列表:
      ${info ?? "购物车为空"}
    -----------------------------
    ''';
    }

    void main() {
      ShoppingCart.withCode(
          name: '张三',
          code: '123456',
          bookings: [Item('苹果', 10.0, count: 1), Item('鸭梨', 20.0, count: 2)])
        ..printInfo();

      ShoppingCart(
          name: '李四', bookings: [Item('香蕉', 15.0), Item('西瓜', 40.0, count: 4)])
        ..printInfo();

      ShoppingCart(name: '王五')..printInfo();
    }
    展开

    作者回复: 计算价格的时候,商品单价要乘以数量;商品合并的时候,数量要置为1

    
    
  • 狗子不要喝奶茶
    2019-10-27
    如果方便的话 能否附上课后问题的 解法。方便对一下~自己的思路

    作者回复: 会有的

    
    
我们在线,来聊聊吧