多态 #

一、多态概述 #

1.1 什么是多态 #

多态是指同一函数调用在不同对象上有不同的行为。Solidity通过函数重写实现多态。

solidity
contract Animal {
    function speak() public pure virtual returns (string memory) {
        return "...";
    }
}

contract Dog is Animal {
    function speak() public pure override returns (string memory) {
        return "Woof";
    }
}

contract Cat is Animal {
    function speak() public pure override returns (string memory) {
        return "Meow";
    }
}

1.2 多态的作用 #

作用 说明
代码复用 统一接口,不同实现
扩展性 易于添加新类型
灵活性 运行时确定行为

二、函数重写 #

2.1 基本重写 #

solidity
contract Parent {
    function getValue() public pure virtual returns (uint256) {
        return 100;
    }
}

contract Child is Parent {
    function getValue() public pure override returns (uint256) {
        return 200;
    }
}

2.2 多重重写 #

solidity
contract A {
    function foo() public pure virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function foo() public pure virtual override returns (string memory) {
        return "B";
    }
}

contract C is A, B {
    function foo() public pure override(A, B) returns (string memory) {
        return "C";
    }
}

2.3 修饰器重写 #

solidity
contract Parent {
    modifier onlyOwner() virtual {
        _;
    }
}

contract Child is Parent {
    modifier onlyOwner() override {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    address public owner;
}

三、super关键字 #

3.1 调用父合约函数 #

solidity
contract Parent {
    uint256 public value;
    
    function setValue(uint256 _value) public virtual {
        value = _value;
    }
}

contract Child is Parent {
    function setValue(uint256 _value) public override {
        super.setValue(_value);  // 调用父合约函数
        value *= 2;  // 额外逻辑
    }
}

3.2 多继承中的super #

solidity
contract A {
    event Log(string message);
    
    function foo() public virtual {
        emit Log("A.foo");
    }
}

contract B is A {
    function foo() public virtual override {
        emit Log("B.foo");
        super.foo();
    }
}

contract C is A {
    function foo() public virtual override {
        emit Log("C.foo");
        super.foo();
    }
}

contract D is B, C {
    function foo() public override(B, C) {
        emit Log("D.foo");
        super.foo();  // 调用C.foo -> B.foo -> A.foo
    }
}

四、动态分发 #

4.1 接口多态 #

solidity
interface IToken {
    function transfer(address to, uint256 amount) external returns (bool);
}

contract TokenA is IToken {
    function transfer(address to, uint256 amount) external override returns (bool) {
        // TokenA的实现
        return true;
    }
}

contract TokenB is IToken {
    function transfer(address to, uint256 amount) external override returns (bool) {
        // TokenB的实现
        return true;
    }
}

contract TokenUser {
    function transferToken(
        IToken token,
        address to,
        uint256 amount
    ) public returns (bool) {
        return token.transfer(to, amount);  // 动态分发
    }
}

五、最佳实践 #

5.1 合理使用virtual/override #

solidity
contract Base {
    // 明确标记可重写的函数
    function template() public pure virtual returns (string memory) {
        return "Base";
    }
    
    // 不希望被重写的函数
    function finalFunction() public pure returns (string memory) {
        return "Final";
    }
}

六、总结 #

多态要点:

特性 说明
virtual 允许重写
override 重写父合约函数
super 调用父合约函数
接口多态 通过接口实现动态分发

接下来,让我们学习库合约!

最后更新:2026-03-27