Home > Software engineering >  How can Kotlin deduce this 'is' as Account type?
How can Kotlin deduce this 'is' as Account type?

Time:12-11

The following Code A is from the main branch of the official sample project.

In Code A, two 'it' are deduced as Account type , and also 'account' is deduced as Account type.

How can Kotlin deduce? You know private fun <T> OverviewScreenCard(...) is generic , and T maybe is any type.

BTW, I think that I should use Code B instead of Code A.

Code A

@Composable
private fun AccountsCard(onClickSeeAll: () -> Unit, onAccountClick: (String) -> Unit) {
    val amount = UserData.accounts.map { account -> account.balance }.sum()
    OverviewScreenCard(
        title = stringResource(R.string.accounts),
        amount = amount,
        onClickSeeAll = onClickSeeAll,
        data = UserData.accounts,
        colors = { it.color },     //  This 'it' is Account type
        values = { it.balance }    //  This 'it' is Account type
    ) { account ->                 //  This 'account' is Account type  
        AccountRow(
            modifier = Modifier.clickable { onAccountClick(account.name) },
            name = account.name,
            number = account.number,
            amount = account.balance,
            color = account.color
        )
    }
}


@Composable
private fun <T> OverviewScreenCard(
    title: String,
    amount: Float,
    onClickSeeAll: () -> Unit,
    values: (T) -> Float,
    colors: (T) -> Color,
    data: List<T>,
    row: @Composable (T) -> Unit
) {
    ...
    
}


@Composable
fun AccountRow(
    modifier: Modifier = Modifier,
    name: String,
    number: Int,
    amount: Float,
    color: Color
) {
    ...
}

Code B

@Composable
private fun AccountsCard(onClickSeeAll: () -> Unit, onAccountClick: (String) -> Unit) {
    val amount = UserData.accounts.map { account -> account.balance }.sum()
    OverviewScreenCard<Account>(                          //I think I need use this
        title = stringResource(R.string.accounts),
        ...
    ) { account ->
       ...
    }
}

CodePudding user response:

Indeed, none of the parameters you have passed to OverviewScreenCard constrains T in any way, except

data = UserData.accounts

UserData.accounts is of type List<Account>. On the right hand side, the data parameter is expecting a List<T>. This constrains what T can be. T can only be Account, or a super type of Account. Otherwise, you wouldn't have been able to pass UserData.accounts to the data parameter.

And since the other parameters you have passed does not constrain the type of T further, the compiler resolves the constraints on T and chooses the most specific type that satisfies them, which is Account.

You can also specify the type directly like you do in Code B, but it is redundant.

  • Related