Черты и реализации в Rust

У меня есть следующие типы:

trait Monster {
    fn attack(&self);
    fn new(int) -> Self;
}

struct CookiesMonster {
    cookies: int,
    hungry_level: int,
}

impl Monster for CookiesMonster {
    fn new(i: int) -> CookiesMonster {
        CookiesMonster { cookies: i, hungry_level: i + 1 }
    }

    fn attack(&self) {
        println!("I have {:d} cookies!!", self.cookies)
    }
}

struct Dummy {
    count: int
}

impl Dummy {
    fn new(i: int) -> Dummy {
        Dummy { count: i }
    }
}

Теперь это работает:

let monster: CookiesMonster = Monster::new(10);
let dummy = Dummy::new(10);

Но это не так:

let monster = CookiesMonster::new(10);

Почему я не могу вызвать новый метод непосредственно в файле CookiesMonster?

Ответ 1

Обратите внимание, что вызов методов в признаке вместо типа, реализующего признак, позволяет сделать такие случаи однозначными: подумайте, добавили ли вы следующий код к вашему примеру:

trait Newable {
    fn new(int) -> Self;
}

impl Newable for CookiesMonster {
    fn new(i: int) -> CookiesMonster {
        CookiesMonster { cookies: i, hungry_level: 0 }
    }
}

В этом контексте Monster::new все еще работает, но CookiesMonster::new будет неоднозначным.

(В этом примере он показывает, как реализовать реализацию этого признака на основе вывода типа. Обобщенный синтаксис, такой как Trait::<for Type>::static_method, обсуждался как способ явно записать одно намерение, но я не уверен, как далека от этого.)

Обновление около 15 июля 2014 года: предложение "Синтаксис единого вызова функции" отслеживает работу, указанную в предыдущем абзаце. См. Rust RFC PR 132. Я понимаю, что UFCS, как описано в RFC, фактически позволит вам писать CookiesMonster::new, когда Monster является единственным признаком в области, который оба (1.) предоставляет метод new, и (2.) однозначно реализован для CookiesMonster.

Ответ 2

Из-за этого, как черты работают в данный момент. Статические методы в признаках должны быть вызваны на черту, а не на исполнителя этого признака.