Сопоставление с начальными значениями в абстрактном классе

#java #kotlin

#java #kotlin

Вопрос:

У меня есть абстрактный класс, который содержит некоторые значения по умолчанию следующим образом

BaseRequest.kt

 abstract class BaseRequest {

    abstract val route: String

    /** Initially, all requests contain the route param, that's why it has to be added for all requests */
    val baseMap: Map<String, String> by lazy { mapOf("route" to route) }

    abstract fun toMap(): Map<String, String>
}
 

Теперь, для всех подклассов, мне нужен любой, кто расширяет BaseRequest класс, чтобы переопределить toMap() функцию и вернуть карту с начальным значением route , которое было инициализировано в базовом классе.

Я имею в виду, что как только пользователь переопределяет карту и заполняет ее любыми значениями, я добавляю к этим значениям значение по умолчанию.

Например

ItemRequest.kt

 class ItemsRequest: BaseRequest() {

    override val route: String = "items"

    override fun toMap(): Map<String, String>  = mapOf("id" to "7")

}
 

Для ItemsRequest класса мне нужно, чтобы возвращаемая карта из toMap() функции имела id значение, а также значение по умолчанию route , без необходимости вручную добавлять ее в каждый подкласс.

Возможно ли это?

Комментарии:

1. В вашем первом фрагменте кода это ROUTE просто заполнитель для фактического значения в вашем коде ради вопроса?

2. @ChrisGong да, я отредактировал это для ясности

3. И можем ли мы предположить, что любые пары ключ-значение на карте из toMap метода не будут переопределять / переопределять пары ключ-значение в baseMap ?

4. В принципе, baseMap была попытка реализовать то, что я пытаюсь сделать, но это не сработало. Таким образом, она может быть изменена или устранена на основе предлагаемого подхода.

Ответ №1:

Я полагаю, вы можете просто объединить карту, которую подкласс намеревается вернуть, с baseMap переменной из суперкласса. Поскольку в своих комментариях вы сказали, что оригинал baseMap может быть изменен, вы можете просто использовать операцию plus между baseMap и любой другой картой, которую вы хотите, чтобы ваш конкретный подкласс возвращал следующим образом,

 override fun toMap(): Map<String, String>  = baseMap   mapOf("id" to "7")
 

Обратите внимание, как baseMap находится в левой части операции plus. В этом случае, если какие-либо ключи существуют в обоих baseMap и в карте справа от операции plus, то конечная карта, возвращаемая из toMap , будет содержать только значения из карты справа от операции plus для ключей, общих для обеих карт. Если вы хотите baseMap , чтобы пары ключ-значение имели приоритет и всегда возвращались из любой карты, возвращаемой из toMap метода любого подкласса, то baseMap справа от операции plus выполните следующее,

 override fun toMap(): Map<String, String>  = mapOf("id" to "7")   baseMap
 

Однако, предполагая, что вы хотите toMap , чтобы реализация каждого подкласса возвращала хотя бы значение baseMap , может быть довольно излишним постоянно писать baseMap ... или ... baseMap снова и снова для каждого подкласса, который переопределяет этот toMap метод. Поэтому мое предложение состояло бы в том, чтобы сделать toMap функцию в родительском классе неабстрактной функцией и определить другую абстрактную функцию только для возврата пользовательского отображения в классы, производные от родительского класса. Вот что я имею в виду под этим,

 abstract class BaseRequest {

    abstract val route: String

    /** Initially, all requests contain the route param, that's why it has to be added for all requests */
    val baseMap: Map<String, String> by lazy { mapOf("route" to route) }

    abstract fun subMap(): Map<String, String>

    // again, up to you with how you want to combine the two maps, 
    // assuming you are okay with key-value pairs being overwritten by one of the maps, 
    // the plus operation is fine
    fun toMap(): Map<String, String> = baseMap   subMap()
}

class ItemsRequest: BaseRequest() {

    override val route: String = "items"

    override fun subMap(): Map<String, String>  = mapOf("id" to "7")

}
 

Обратите внимание, что subMap функция также может быть переменной, как и то, как вы сделали route переменную. И теперь toMap функция для каждого производного класса BaseRequest будет возвращать комбинацию baseMap и subMap() .

Комментарии:

1. Большое вам спасибо, subMap подход — это то, что я искал.