質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

3751閲覧

Kotlinでメンバ変数を参照しかできなくする方法

REIK727

総合スコア23

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2018/12/24 19:54

編集2018/12/24 23:01

まずこの分野については超超超初心者なので全体的に乱文となっております。ご了承ください。

現在Kotlinを使ってandroidアプリを作っています。その最中、複数のアクティビティで参照したいデータができたのでそれをグローバル変数にすることにしました。グローバル変数はApplicationクラスを継承したクラス(以下Xとする)のメンバとするわけですが、今回のデータはXのメンバ関数onCreate()で初期化した後はXの外からは参照だけできればいいので、書き換えは一切禁止したいです。
~~そこでいろいろ調べた結果setterをprivateにすれば書き換えはできなくなるとわかったのですが、~~しかし関数を通じて状態を変更することは可能でした(グローバル変数にしたいものにArrayListが含まれていたが、Xの外からでもadd()を呼び出すことが可能だった)。こうした形での変更すら禁止することは可能なのでしょうか?


グローバル変数を格納しているクラス

kotlin

1package com.example.sample 2 3import android.app.Application 4 5class Global : Application() { 6 /*↓この"al"をGlobalクラスの外から見えるようにはしたいが、中身をいじられたくはない*/ 7 val al = ArrayList<Int>() 8 9 override fun onCreate() { 10 super.onCreate() 11 12 /*alの初期化。あくまで一例。*/ 13 for (i in 0..100) { 14 al.add(i) 15 } 16 } 17}

そのグローバル変数を参照しているアクティビティ

kotlin

1package com.example.sample 2 3import android.support.v7.app.AppCompatActivity 4import android.os.Bundle 5 6class MainActivity : AppCompatActivity() { 7 override fun onCreate(savedInstanceState: Bundle?) { 8 super.onCreate(savedInstanceState) 9 setContentView(R.layout.activity_main) 10 11 val glob = application as Global 12 13 /*中身は見たい*/ 14 val num = glob.al[0] 15 /*でもこれはできないようにしたい*/ 16 glob.al.add(1) 17 } 18}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/12/24 22:01

そのコードを提示しましょう
m.ts10806

2018/12/24 22:26

定数宣言ができればいいとかそういうことでしょうか。そもそもsetterはprivateにしたメンバ変数を参照させるためのものですので「privateにすれば」というのはやり方が違っているという風にも思います。
REIK727

2018/12/24 23:02

同じ状況になっているコードを例として載せました。また、setterについてはこちらでもコードを整理しているうちに解決しました。
REIK727

2018/12/25 06:03

すみません、教えてくださった記事の具体的にどの辺が解決策につながるのかよくわかりませんでした... また、今回はde9様が解決策を示してくださったので、申し訳ないのですがそちらをベストアンサーにして解決済みにしたいと思います。 ご協力誠にありがとうございました。
m.ts10806

2018/12/25 06:05

> // 値の変更不可 val value = 1 // 値の変更可 var value = 1
REIK727

2018/12/25 06:14

件のArrayListをval宣言すれば定数になって書き換えができなくなる、ということでしょうか? しかしそれでもadd()等の関数は呼び出せてしまいます(実際上のコードでもalはval宣言されています)。
m.ts10806

2018/12/25 06:16 編集

間違えました。
REIK727

2018/12/25 06:19

すみませんがおっしゃっていることがよくわかりません。
m.ts10806

2018/12/25 06:22 編集

読み違えてました。スルーしてください。失礼しました。
m.ts10806

2018/12/25 06:22

コメント修正しています。失礼しました
REIK727

2018/12/25 06:22

いえ、こちらこそつい攻撃的な口調になってしまいました。とにかくご協力ありがとうございました。
guest

回答1

0

ベストアンサー

KotlinのArrayListはMutableListの実装であるため、al自体が読み取り専用(val)であってもadd等のメソッドは呼び出し可能です。
add等のメソッドを持たないListとしてalを宣言すれば外から弄られないのですが、そうすると今度はonCreateでaddメソッドが呼び出せず困ってしまいますね。

解決手段として、以下のようにプロパティをわけるという手があります。

Kotlin

1class Global : Application() { 2 private val _al = ArrayList<Int>() 3 val al: List<Int> get() = _al 4 5 override fun onCreate() { 6 super.onCreate() 7 8 for (i in 0..100) { 9 _al.add(i) 10 } 11 } 12}

こうするとクラスの外ではList型のalしか見えず、クラスの内からは中身をいじれるArrayListの_alが見える状態になります。

ただし実体がArrayListであることには変わりないので、何をしても以下のようにキャストすればaddできてしまいます。注意が必要ですね。

Kotlin

1val al = glob.al 2if (al is ArrayList<Int>) { 3 al.add(0) 4}

投稿2018/12/25 02:18

de9

総合スコア312

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

REIK727

2018/12/25 06:42

Kotlinはまだ始めたばかりなので文法も正確には把握できていないのですが、 ・getterやsetterは(提示してくださったコードの"al"のように)名前を付けることができる ・そこからListにキャストした_alを返している という認識であっていますか?
REIK727

2018/12/25 07:04 編集

あ、「alというpublicなListを作り、そのalのgetterから(Listに変換された)_alを返している」ということですね。完全に理解しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問