Вы в основном верны.
Существует ловкий трюк, чтобы компилятор сказать вам тип переменных, а не пытаться вывести их: let() = ...;
.
Использование the Playground я за 1-й случай:
9 | let() = self;
| ^^ expected &Self, found()
и 2-й случай:
16 | let() = self;
| ^^ expected &Circle, found()
Первый случай действительно особенным, потому что HasArea
не является типом, это черта.
И что такое self
? Это ничего еще.
Сказал иначе, он представляет для любой возможный конкретный тип, который может реализовать HasArea
. И, таким образом, единственная гарантия, которую мы имеем об этой особенности, заключается в том, что она обеспечивает не менее интерфейс HasArea
.
Главное, что вы можете разместить дополнительные ограничения. Например, вы могли бы сказать:
trait HasArea: Debug {
fn area(&self) -> f64;
}
И в этом случае, Self: HasArea + Debug
, что означает, что self
обеспечивает как интерфейсы HasArea
и Debug
.
Вторые и третьи случаи гораздо проще: мы знаем, типточного бетона, для которого реализовано HasArea
черты. Это Circle
.
Таким образом, тип self
в методе fn area(&self)
составляет &Circle
.
Обратите внимание, что если тип параметра равен &Circle
, то из этого следует, что во всех его применениях в методе это &Circle
. Ржавчина имеет статическую типизацию (и не зависящую от потока ввода), поэтому тип привязки не меняется во время его жизни.
Однако все может усложниться.
Представьте, что у вас есть две черты:
struct Segment(Point, Point);
impl Segment {
fn length(&self) -> f64;
}
trait Segmentify {
fn segmentify(&self) -> Vec<Segment>;
}
trait HasPerimeter {
fn has_perimeter(&self) -> f64;
}
Затем, вы можете реализовать HasPerimeter
автоматически для всех форм, которые могут быть разбиты в последовательности сегментов.
impl<T> HasPerimeter for T
where T: Segmentify
{
// Note: there is a "functional" implementation if you prefer
fn has_perimeter(&self) -> f64 {
let mut total = 0.0;
for s in self.segmentify() { total += s.length(); }
total
}
}
Какое здесь значение self
? Это &T
.
Что такое T
? Любой тип, который реализует Segmentify
.
И поэтому все, что мы знаем о T
, что она реализует Segmentify
HasPerimeter
и, и больше ничего (мы не могли использовать println("{:?", self);
потому T
не гарантируется для реализации Debug
).
Возможно, вас заинтересует [В чем разница между 'self' и' Self'] (http://stackoverflow.com/questions/32304595/whats-the-difference-between-self-and-self). –
Вопрос о 'self.radius' немного отличается от вопроса о себе (речь идет о собственности и' Copy'). Я предлагаю вам отредактировать его, чтобы сосредоточиться на том, что «сам» здесь, так как это самая сложная (и новая) часть, тогда как у нас уже много вопросов о собственности. –