APIで取得したJsonデータをパース、Modelメンバにパースした値をセットしてオブジェクトを返す。という処理をtemplate method的な固有実装のみサブクラスに実装したかったので勉強しました。
クラス関係
//ジェネリクスは継承先のクラスが指定する open abstract class ApiModel<T> { } class DataModel:ApiModel<BlogModel>() { var last_name = "" //jsonから取得した値が入ります var first_name = "" }
抽象メソッドの定義と実装
各サブラクスにmodelオブジェクトを生成する処理を記述する
open abstract class ApiModel<T> { abstract fun createModel(jsonObject:JSONObject):T } class DataModel:ApiModel<DataModel>() { var last_name = "" //jsonから取得した値が入ります var first_name = "" override fun createModel(jsonObject:JSONObject):DataModel{ val model = DataModel() model.last_name = jsonObject.getString("last_name") model.first_name = jsonObject.getString("first_name") return model } }
親クラスにtemplate methodの呼び出しメソッドを記述
Superクラスはサブクラスから渡されたジェネリクスに応じたオブジェクトを呼び出し元に返せばよい
open abstract class ApiModel<T> { abstract fun createModel(jsonObject:JSONObject):T //jsonが配列の場合 fun stringToModels(apiResponseJson: String):List<T>{ val returnModels = mutableListOf<T>() val jsons = JSONArray(apiResponseJson) (0..(jsons.length() - 1)).forEach { i -> //createModelはサブクラスで実装 val model = createModel( jsons.getJSONObject(i) ) returnModels.add(model) } return returnModels as List<T> } //jsonが単オブジェクトの場合 fun stringToModel(apiResponseJson: String):T{ val json = JSONObject(apiResponseJson) //createModelはサブクラスで実装 val model = createModel( json ) return model } }
使用例
val dataModel:DataModel = DataModel().stringToModel("単オブジェクトのJson文字列") val dataModels:List<DataModel> = DataModel().stringToModels("ルートが配列のJson文字列")
他のAPIを使用するクラスの場合、
class FooModel:ApiModel<FooModel>() { var foo_name = "" override fun createModel(jsonObject:JSONObject):FooModel{ val model = FooModel() model.foo_name = jsonObject.getString("foo_name") return model } }
と、こんな感じでジェネリクスとJsonに関わる構造のみ記述すればよい。
リンク
リンク