Near Learn

No inheritance: traits & composition

Rust has no contract inheritance. Shared behavior comes from traits (with default methods) and shared state from composition.

Beginner4 min read3-question check

Solidity leans on inheritance — contract Token is Ownable, Pausable. Rust has no implementation inheritance at all. You reuse code two other ways: traits for shared behavior (they can carry default methods) and composition for shared state (embed a struct).

Reusing an "Ownable" behavior
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

abstract contract Ownable {
    address public owner;
    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }
}

// inherit owner + onlyOwner
contract Token is Ownable {
    uint256 public supply;
}
Rust
use near_sdk::{near, env, require, AccountId};

// shared BEHAVIOR as a trait with a default method
trait Ownable {
    fn owner(&self) -> &AccountId;

    fn assert_owner(&self) {
        require!(env::predecessor_account_id() == *self.owner(), "not owner");
    }
}

// shared STATE by composition — embed the owner field
#[near(contract_state)]
pub struct Token {
    owner: AccountId,
    supply: u128,
}

// implement the one required method; get assert_owner for free
impl Ownable for Token {
    fn owner(&self) -> &AccountId {
        &self.owner
    }
}
Coming from EVM

contract Token is Ownable ↔ impl Ownable for Token. A trait with default methods (assert_owner) is the closest thing to inheriting a base function or modifier — you implement the small required piece and get the rest.

Shared *state* is composition, not inheritance: you embed the fields (or a whole sub-struct) you need. There is no diamond problem and no super — just fields and trait methods.

For the token standards, near-contract-standards gives you structs to embed plus macros that generate the trait impls — that is how you "inherit" NEP-141/171 behavior in practice.

Check yourself

3 questions · progress saved in this browser

  1. 1.How does Rust replace contract Token is Ownable?
  2. 2.Without inheritance, how is shared state such as an owner field reused?
  3. 3.In practice, how do you "inherit" NEP-141 / NEP-171 behavior?