クラスベースの言語から来た身としては、変に悩んでしまったのでメモとして残しておきます。
やりたいこと:Java での実装例
タイトルだけでは何がしたいのかさっぱりわからないと思うので、実現したいことを Java で書くと以下のような感じです:
import java.util.*;
interface Service {
int ID = 123;
void displayId();
}
class Module implements Service {
public void displayId() {
System.out.println(getId());
}
private int getId() {
return this.ID;
}
}
public class Main {
public static void main(String[] args) {
Module module = new Module();
module.displayId();
}
}
要は、
- インタフェース(Rust ではトレイト)で public なメソッドを1つ列挙しておきたい
- 実装クラス(Rust では impl)の中で、 private なメソッドを定義して利用したい
の2点です。
Rust で実現:失敗例
これを Rust で実現しようとこのように書くとコンパイルエラーが出て怒られます:
trait Service {
fn display(&self);
}
struct Module {
id: u64,
}
impl Service for Module {
fn display(&self) {
print!("{}", get_id());
}
fn get_id(&self) -> u64 {
self.id
}
}
fn main() {
let module = Module{
id: 12,
};
module.display();
}
エラーメッセージは、error[E0407]: method get_id is not a member of trait Service
と error[E0425]: cannot find function get_id in this scope
というものです。 get_id
というメソッドは Service
トレイトで列挙していないので、書けないよ と怒られてしまいます。
Rust で実現:成功例
ということで、以下のようにするとコンパイラに怒られずに済みます:
trait Service {
fn display(&self);
}
struct Module {
id: u64,
}
impl Service for Module {
fn display(&self) {
print!("{}", self.get_id());
}
}
impl Module {
fn get_id(&self) -> u64 {
self.id
}
}
fn main() {
let module = Module{
id: 12,
};
module.display();
}
直したのは、 Service
トレイトの実装 Module
をトレイトの実装部分( impl Service for Module
の箇所)と Module 独自のメソッドを定義する部分( impl Module
の箇所)に分けて書く、という点です。
こうすれば、最初に Java の例で挙げたのと同じ動作が実現できます。
謝辞
この問題の解決にあたっては、rust-jp.rs の 日本語コミュニティ(Slack)の方々にお世話になりました。初心者の私の質問に迅速に丁寧にご回答いただき、非常に助かりました。