はじめに
私はオブジェクト指向言語の経験者なのですが、
オブジェクト指向でいうところのクラスはRustの構造体という記事を見てから積極的に構造体が使えるようになってきました。
コーディングを進める中で、モジュールの構造体のフィールドをPrivateにしたい場合が出てきました。
しかし外部から利用するにはPublicにせざるを得ません。
解決方法は、日本語ドキュメントにありました。(おわり)
この記事は、基本的に以下ページに書いてあることのままですが、ドキュメントを一読しただけでは利用場面が想像しづらかったので整理しました。
PublicとPrivateを考慮できていないパターン
まずは、コンパイルエラーになる書き方から見ていきます。
CatData
はPublicですが、name
, returnCode
はPrivateなのでコンパイルエラーになります。
// 構造体
pub struct CatData {
name: String,
return_code: String
}
// 何らかの処理
let name = "Tama";
let tama_rescode = getCatData(name);
// インスタンス化
let cat = CatData {
name: name.to_string(), // field `name` of struct `xxx::CatData` is private
return_code: tama_rescode // field `return_code` of struct `xxx::CatData` is private
};
// 利用
println!("returnCode: {}", cat.return_code); // field `return_code` of struct `xxx::CatData` is private
解決方法①:Publicなフィールドを持つPublicな構造体にする
フィールドの前にpub
をつけるだけでコンパイルがとおります。
// 構造体
pub struct CatData {
pub name: String,
pub return_code: String
}
問題は、フィールドを公開したくない場合です。
例の場合、name
は外部参照される予定がありませんが、pub
にせざるを得ない状況です。
解決方法②:PrivateなフィールドとPublicなコンストラクタメソッドを持つ構造体にする
// 構造体
pub struct CatData {
kind: String, // 外部から更新されないフィールドも使える
name: String,
return_code: String
}
// 構造体CatDataのメソッド(メソッドとはオブジェクトに付属した関数)を定義
impl CatData {
// Publicなコンストラクタメソッド
pub fn new(name: &str, response_code: String) -> CatData {
CatData {
kind: "Animal".to_string(),
name: name.to_string(),
response_code: response_code
}
}
// response_codeを外部から利用するためのPublicメソッド
pub fn get_code(&self) -> String {
self.response_code.clone()
}
// 何らかの処理
let name = "Tama";
let tama_rescode = getCatData(name);
// インスタンス化
let cat = CatData::new(name, tama_rescode);
// 利用
println!("returnCode: {}", cat.get_code());
おわりに
ありがとうございました。
ほぼオブジェクト指向の設計で進められているのですが、Rustにクラスがないことの意味をちゃんと考えたほうがいいかもしれません。
なおWikipediaには、マルチパラダイムプログラミング言語
と書かれていました。
Rustはマルチパラダイムプログラミング言語であり、手続き型プログラミング、オブジェクト指向プログラミング、関数型プログラミングなどの実装手法をサポートしている。
すごい。