4 Stimmen

Muss ich ein Trait 'verwenden', um die darin definierten Methoden aufzurufen?

Ich spiele mit der cgmath-Bibliothek herum. Ich habe die folgende main.rs-Datei:

extern crate cgmath;

use cgmath::vector::{Vector3, EuclideanVector};

fn main() {
    let mypoint = Vector3 { x: 1f64, y: 1f64, z: 3f64 };

    println!("Die Länge des Vektors beträgt {}, und die Länge im Quadrat beträgt {}", mypoint.length(), mypoint.length2());
}

In meiner Verwendungszeile, wenn ich EuclideanVector weglasse, erhalte ich folgenden Kompilierungsfehler:

type 'cgmath::vector::Vector3' implementiert keine Methode namens 'length' im Scope.

Es scheint, dass der Rust-Compiler die Methode length() nicht finden kann, es sei denn, ich importiere eines der Traits, die Vector3 verwendet. Wenn ich in den Quellcode eintauche, scheint die Längenmethode im EuclideanVector-Trait definiert zu sein.

Intuitiv sollte ich keinen Trait importieren müssen, um einen Typ zu verwenden, der den besagten Trait erbt. Gibt es eine Technik, um das zu tun, was mir entgeht? Ist dies eine Nuance spezifisch für die cgmath-Bibliothek? Ist dies ein Bestandteil von Rust, an den ich mich gewöhnen sollte?

6voto

SteveMcQwark Punkte 2021

Sie denken bei Eigenschaften im Sinne von Vererbung. Es könnte sinnvoller sein, eine Eigenschaft als Modul zu betrachten, das mit Blick auf den Self-Typ überladbar ist. Aus dieser Perspektive macht es Sinn, dass die Eigenschaft im Scope sein muss, damit der Compiler über ihre Methoden Bescheid weiß, genauso wie ein Modul im Scope sein muss, um es zu verwenden. Eine besondere Auswirkung davon ist, dass Implementierungen neben der Eigenschaft, die sie implementieren, deklariert werden können, anstatt neben dem Typ, für den sie implementiert sind. In dieser Situation ist klar, dass dein Code, wenn er nichts über die Eigenschaft weiß, ihre Methoden nicht verwenden kann.

Ein weiteres Motiv für das aktuelle Verhalten ist, dass mehrere Eigenschaften Methoden mit dem gleichen Namen definieren können, und wenn es einen Konflikt für Eigenschaften gibt, die für denselben Typ implementiert sind, kannst du nicht mehr die Methoden mit Methodenaufruf-Syntax aufrufen. Stattdessen musst du Funktionsaufruf-Syntax verwenden, um anzugeben, zu welcher Eigenschaft die Methode gehört (die Eigenschaft fungiert als das Modul, in dem sich die Methode befindet). Wenn die Methodenaufruf-Syntax alle Eigenschaften in deinem Programm anstelle nur derjenigen im Scope für die Methodenauflösung verwenden würde, würdest du diese Konflikte viel öfter haben, da du Namenskonflikte mit Methoden in Eigenschaften hättest, die dein Code tatsächlich nicht direkt verwendet.

3voto

kvark Punkte 5171

Im strengen Sinne müssen Sie nicht use verwenden. Alternativ:

(&mypoint as &cgmath::vector::EuclideanVector).length2()

1voto

Steve Klabnik Punkte 12680

Ja, so funktioniert Rust. Du musst immer ein Trait importieren, bevor du seine Methoden verwenden kannst. Das ist absichtlich so.

1voto

real-or-random Punkte 222

Wenn Sie wirklich nicht importieren möchten, können Sie cgmath::vector::EuclideanVector::length(&mypoint) aufrufen.

(Ich weiß nicht, ob das möglich war, als die Frage gestellt wurde.)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X