#kotlin
#kotlin
Вопрос:
Я хочу сделать так, чтобы мой код оставался сухим и создавал 3 (или больше, или меньше) кнопки с примерно одинаковой структурой. Итак, я создаю список объектов для перебора и помещаю данные внутри объекта для использования в нескольких местах в AppButton.
Я мог бы подумать, что это слишком Pythonic, потому что это мой основной язык, и я только недавно начал использовать Kotlin. Что я обычно делаю в Python:
app_buttons = [
dict(
text="....",
icon="....",
uri_string="....",
),
...
]
Я пробовал что-то подобное в Kotlin с mapOf
:
val appButtons = arrayOf(
mapOf(
"title" to getString(R.string.app_btn_example1),
"icon" to R.drawable.ic_some_icon_1_64,
"uriString" to "myapp://example1",
),
...
)
а затем перебирать их и получать с карты:
for (entry in appButtons) {
buttons.add(
AppButton(
entry.get("text"),
entry.get("icon"),
) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.get("uriString"))).apply {
val name = getString(R.string.saved_account_key)
putExtra(name, sharedPref.getString(name, null))
}
startActivity(intent)
}
)
}
Но потом я получаю Type mismatch. Required String. Found {Comparable amp; java.io.Serializable}?
. Я не знаю, какие типы куда поместить…
Хорошо, другой подход, использование setOf
и разрушение:
val appButtons = arrayOf(
setOf(
getString(R.string.app_btn_example1),
R.drawable.ic_some_icon_1_64,
"myapp://example1",
),
...
)
for ((text, icon, uriString) in appButtons) {
buttons.add(
AppButton(
text,
icon
) {
...
}
)
}
Но теперь я получаю следующее:
Инициализатор объявления деструктурирования типа Set<{Comparable<*> amp; java.io.Serializable}> должен иметь функцию ‘component1 ()’
Инициализатор объявления деструктурирования типа Set<{Comparable<*> amp; java.io.Serializable}> должен иметь функцию ‘component2 ()’
Инициализатор объявления деструктурирования типа Set<{Comparable<*> amp; java.io.Serializable}> должен иметь функцию ‘component3 ()’
Как мне заставить это работать? Как мне создать базовый список объектов и перебирать их с правильными типами? В Python это так просто. Я явно что-то упускаю.
Комментарии:
1. Пожалуйста, не используйте карты таким образом. Создайте класс данных с именем
ButtonModel
или что-то в этом роде.2. @Sweeper да, вот почему я спрашиваю. Я чувствую, что делаю что-то не так, но я не знаю, что и как это должно быть сделано.
3. Kotlin (во всяком случае, в JVM) — это статически типизированный язык (где типы,
Int
,String
и т.д. известны во время компиляции), Python динамически типизируется (типы проверяются во время выполнения). Это позволяет вам создаватьdict
s, которые содержат в основном все, что угодно, и вам решать, чтобы убедиться, что извлеченный материал обрабатывается правильно — вы должны знатьicon
, что это anInt
и рассматривать его как один, иначе вы получите сбой во время выполнения. Вы не можете (обычно) делать это на статически типизированных языках — они обеспечивают правильное использование типов, поэтому вы не можете смешивать их на карте. Структура данных, подобная ответу Sweeper, — это то, что вам нужно!
Ответ №1:
Вместо того, чтобы использовать карты, вы должны создать класс данных. Например:
data class ButtonModel(
val title: String,
val icon: Int,
val uriString: String,
)
Затем вы можете создать массив следующим образом:
val appButtons = arrayOf(
ButtonModel(
title = getString(R.string.app_btn_example1),
icon = R.drawable.ic_some_icon_1_64,
uriString = "myapp://example1",
),
...
)
Или без меток параметров, если вы предпочитаете:
val appButtons = arrayOf(
ButtonModel(
getString(R.string.app_btn_example1),
R.drawable.ic_some_icon_1_64,
"myapp://example1",
),
...
)
Затем, вместо того, чтобы получать их с get
помощью или []
, вы можете просто использовать синтаксис dot:
buttons.add(
AppButton(
entry.text,
entry.icon,
) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.uriString)).apply {
val name = getString(R.string.saved_account_key)
putExtra(name, sharedPref.getString(name, null))
}
startActivity(intent)
}
)
Комментарии:
1. В крайнем случае, вы могли бы использовать
Triple
для этого. Но пользовательский класс намного понятнее, безопаснее и удобочитаем. (Это также очень быстро определяется в Kotlin; это может быть даже однострочный!)