有没有一种方法可以创建带有更新的某些字段值的枚举的副本?

时间:2019-01-12 18:51:07

标签: rust

我有一个带有多个记录变体的枚举:

enum A {
    Var1 { a: i64, b: i64 },
    Var2 { c: i32, d: i32 },
}

我想为这种枚举创建一个修改后的副本(每个变体的行为各不相同)。我知道我可以做到:

match a {
    A::Var1 { a, b } => A::Var1 { a: new_a, b },
    A::Var2 { c, d } => A::Var2 { c, d: new_d },
}

但是,每个变体都有很多字段,我不希望将它们全部显式传递。有什么办法说“克隆这个枚举,除了将此值用于字段x而不是克隆的值”?

2 个答案:

答案 0 :(得分:4)

不完全是。 有“功能记录更新语法”,但仅适用于public double get_distance(String from, String to) { source = new Location("to"); destination = new Location("form"); DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("users"); GeoFire geoFire = new GeoFire(databaseReference); geoFire.getLocation(from, new LocationCallback() { @Override public void onLocationResult(String key, GeoLocation location) { source.setLatitude(location.latitude); source.setLongitude(location.longitude); Log.e("source latlong b4 ",source.getLatitude()+" .. "+source.getLongitude()); // the right value is passed } @Override public void onCancelled(DatabaseError databaseError) { } }); Log.e("source latlong ",source.getLatitude()+" .. "+source.getLongitude()); //value hase turned into 0.0 geoFire.getLocation(to, new LocationCallback() { @Override public void onLocationResult(String key, GeoLocation location) { destination.setLatitude(location.latitude); destination.setLongitude(location.longitude); } @Override public void onCancelled(DatabaseError databaseError) { } }); Log.e("destination latlong", destination.getLatitude()+" .. "+destination.getLongitude()); dist= source.distanceTo(destination); return dist; } s:

segmentedControl.attributedSelectedTitles

在不为每个变体创建结构的情况下,您可以做的最好的事情是这样的:

struct

答案 1 :(得分:1)

恐怕您会因为其设计而遇到对Rust的限制之一,而唯一的真正解决方案是就地进行突变并编写一个或四个mutator函数。

枚举的问题是您需要使用match才能对它们执行任何操作。在那之前,Rust很少了解或推断出该结构实际​​是什么。另一个问题是,缺少任何一种类似于反射的能力来允许查询类型并确定其是否具有字段,并且除了完全匹配所有内容外,无能为力。

老实说,最干净的方法实际上可能取决于您突变的目的。它们是否基于某种业务问题对enum进行了一组定义的更改?如果是这样,您实际上可能希望将逻辑包装到特征扩展中,并使用它来封装逻辑。

例如,考虑一个非常人为的示例。我们正在构建一个必须处理不同项目并向它们征税的应用程序。上述税金取决于产品的类型,由于某种原因,我们所有的产品均以enum的变体形式表示,如下所示:     #[派生(调试)]     列举项{         食物{价格:u8,卡路里:u8},         技术{价格:u8},     }

trait TaxExt {
    fn apply_tax(&mut self);
}
impl TaxExt for Item {
    fn apply_tax(&mut self) {
        match self {
            &mut Item::Food {
                ref mut price,
                calories: _,
            } => {
                // Our food costs double, for tax reasons
                *price *= 2;
            }
            &mut Item::Technology { ref mut price } => {
                // Technology has a 1 unit tax
                *price += 1;
            }
        }
    }
}

fn main() {
    let mut obj = Item::Food {
        price: 3,
        calories: 200,
    };
    obj.apply_tax();
    println!("{:?}", obj);
}

playground

假设您可以像这样拆分逻辑,这可能是构建此逻辑的最干净的方法。