---
title: 常数
description: 无法通过重新赋值更改的不可变值
---

Tact 中的常量可以比流行语言中的常量更先进一些：它们可以是虚拟的、抽象的。 智能合约通常需要实现多个特征，有时您需要在编译时配置其中的一些特征。 禁止使用trait中的构造函数，因为它们的行为不可预测。 因此，我们必须使用常量和字段来传递值。 主合约的任务是为所有特征实现数值和常量。

## 简单常数

让我们从一个简单的常数开始。 这是一个在编译时定义的值，不能更改。 您可以在顶层或合约/trait中定义常量。 让我们在顶层定义一个常量：

```tact
const MY_CONSTANT: Int = 42;
```

特征和合约也类似：

```tact
trait MyTrait {
    const MY_CONSTANT: Int = 42;
}

contract MyContract {
    const MY_CONSTANT: Int = 42;
}
```

## 虚拟常量和抽象常量 {#virtual-and-abstract-constants}

虚拟常量是可以在trait中定义但在合约中改变的常量。 当您需要在编译时配置某些特征时，它非常有用。 让我们定义一个虚拟常量和一个抽象常量： 当您需要在编译时配置某些特征时，它非常有用。 让我们定义一个虚拟常量和一个抽象常量：

```tact
trait MyTrait {
    virtual const MY_FEE: Int = ton("1.0");
}

trait MyAbstractTrait {
    abstract const MY_DEV_FEE: Int;
}
```

现在，您可以覆盖合约中的默认设置：

```tact
contract MyContract with
    MyTrait,
    MyAbstractTrait, // trailing comma is allowed
{
    override const MY_FEE: Int = ton("0.5");
    override const MY_DEV_FEE: Int = ton("1000");
}
```

这对于帮助编译器在编译时获得某些值可能非常有用，例如，您可以启用或禁用功能，而无需修改代码，也不会浪费 gas 。

```tact
trait Treasure {
    virtual const ENABLE_TIMELOCK: Bool = true;

    receive("Execute") {
        if (self.ENABLE_TIMELOCK) {
            //
            // This branch would be removed in compile time if ENABLE_TIMELOCK is false
            //
        }
    }
}

contract MyContract with Treasure {
    override const ENABLE_TIMELOCK: Bool = false;
}
```
