# public、private、external、internal的区别

By [Untitled](https://paragraph.com/@0xc994df6bd78b5e78d4e820a57d65b4efd33bf936) · 2024-12-06

---

     在 Solidity 中，public、private、external 和 internal 是用于控制函数和状态变量可见性的关键字。它们决定了谁可以访问合约中的数据和函数。以下是详细的区别和适用场景：

**1\. public**

*   **特点**：
    
    *   函数或变量可以被**合约内部、继承合约**以及\*\*外部（包括其他合约和用户）\*\*访问。
        
    *   Solidity 会自动为 public 状态变量生成一个**getter 函数**，方便外部读取。
        
*   **适用场景**：
    
    *   任何需要对外公开的函数或变量。
        
*   **示例：**
    

    contract Example {
        uint256 public count; // 自动生成 getter 函数
    
        function increment() public {
            count += 1; // 任何人都可以调用
        }
    }
    

**2\. private**

*   **特点**：
    
    *   只能在**当前合约内部**访问，不能被继承合约或外部访问。
        
    *   适用于需要隐藏实现细节或保护敏感数据的场景。
        
*   **适用场景**：
    
    *   仅在当前合约中使用的辅助函数或数据。
        
*   **示例**：
    

    contract Example {
        uint256 private secretNumber;
    
        function setSecret(uint256 _number) public {
            secretNumber = _number; // 内部设置
        }
    
        function getDoubleSecret() public view returns (uint256) {
            return secretNumber * 2; // 内部访问
        }
    }
    

**3\. internal**

*   **特点**：
    
    *   可以在**当前合约内部**和**继承合约**中访问，但不能被外部访问。
        
    *   适用于共享逻辑和数据的合约继承场景。
        
*   **适用场景**：
    
    *   在继承关系中共享功能。
        
*   **示例**：
    

    contract Parent {
        uint256 internal sharedData;
    
        function setSharedData(uint256 _data) internal {
            sharedData = _data;
        }
    }
    
    contract Child is Parent {
        function updateData(uint256 _newData) public {
            setSharedData(_newData); // 子合约可以访问
        }
    }
    

**4\. external**

*   **特点**：
    
    *   函数只能被**合约外部调用**，不能在合约内部直接调用（除非使用 this 关键字）。
        
    *   更适合**接口和跨合约调用**。
        
    *   函数参数使用 calldata，从而节省 Gas。
        
*   **适用场景**：
    
    *   公开但仅用于外部调用的函数。
        
*   **示例**：
    

    contract Example {
        function externalFunction() external view returns (string memory) {
            return "This is an external function";
        }
    
        function callExternal() public view returns (string memory) {
            return this.externalFunction(); // 需要通过 this 调用
        }
    }
    

**  
总结：**

![public、private、internal、external区别](https://storage.googleapis.com/papyrus_images/e437bb9ec5a1639fdeaa5e54ce225e0b7b9db2e1cf446be3bf2c602739b7d335.png)

public、private、internal、external区别

**完整示例：**

    pragma solidity ^0.8.0;
    
    contract VisibilityExample {
        uint256 public publicNumber = 1;       // 任何人都可以读取
        uint256 private privateNumber = 2;     // 只能在本合约内使用
        uint256 internal internalNumber = 3;   // 当前合约及继承合约可访问
    
        // 公开函数
        function getPublicNumber() public view returns (uint256) {
            return publicNumber;
        }
    
        // 内部函数，仅合约内和继承合约可调用
        function setInternalNumber(uint256 _num) internal {
            internalNumber = _num;
        }
    
        // 私有函数，不能被继承和外部调用
        function setPrivateNumber(uint256 _num) private {
            privateNumber = _num;
        }
    
        // 外部函数，不能内部直接调用
        function externalFunction() external view returns (uint256) {
            return internalNumber;
        }
    
        function testVisibility() public view returns (uint256) {
            return internalNumber; // 可访问 internal 变量
        }
    }
    
    contract ChildContract is VisibilityExample {
        function updateInternal() public {
            setInternalNumber(10); // 可以调用父合约的 internal 函数
        }
    }
    

> **最佳实践：**
> 
> • public：用于需要对外公开访问的函数和变量。
> 
> • private：保护敏感逻辑，避免外部或继承合约访问。
> 
> • internal：在父子合约之间共享逻辑。
> 
> • external：为接口或跨合约交互设计的函数。
> 
> 通过合理使用可见性修饰符，可以提高合约的安全性和效率。

---

*Originally published on [Untitled](https://paragraph.com/@0xc994df6bd78b5e78d4e820a57d65b4efd33bf936/public-private-external-internal)*
