为什么在这个例子中保留子类型而不使用 out 关键字?
Why is subtyping preserved in this example without using the out keyword?
这里有一个泛型,但我不明白为什么即使我没有使类型 T 协变,我也可以将 Player 的子classes 添加到我的泛型中class 和具有上限 T 的函数:Player;那么为什么在不使用 out 关键字的情况下保留子类型;因此,我可以 - 错误地 - 将 BaseballPlayer 和 GamesPlayer 添加到足球队。 1
class Team<T : Player>(val name: String, private val players: MutableList<T>) {
fun addPlayers(player: T) {
if (players.contains(player)) {
println("Player: ${(player as Player).name} is already in the team.")
} else {
players.add(player)
println("Player: {(player as Player).name} was added to the team.")
}
}
}
open class Player(open val name: String)
data class FootballPlayer(override val name: String) : Player(name)
data class BaseballPlayer(override val name: String) : Player(name)
data class GamesPlayer(override val name: String) : Player(name)
val footballTeam = Team<Player>(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
val baseballPlayer = BaseballPlayer("Baseball Player")
val footballPlayer = FootballPlayer("Football Player")
val gamesPlayer = GamesPlayer("Games Player")
footballTeam.addPlayers(baseballPlayer)
footballTeam.addPlayers(footballPlayer)
footballTeam.addPlayers(gamesPlayer)
您在此行定义的可变列表:
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
不是 MutableList<FootballPlayer>
。它是一个 MutableList<Player>
,因为你没有指定它的类型,所以编译器使用类型推断来假设你想要一个 MutableList<Player>
来适合你的 Team<Player>
构造函数的构造函数参数。
因此,将任何类型的 Player
放入 MutableList<Player>
中都是有效的,因为它只能 return 类型 Player
的项目。它仍然是类型安全的。
如果您明确说明了类型,那将是一个编译错误:
val footballTeam = Team<Player>(
"Football Team",
mutableListOf<FootballPlayer>(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
//error, expected MutableList<Player>
)
或者,如果您在团队构造函数中省略了类型,它会假定您想要一个 Team<FootballPlayer>
,并且在尝试添加其他类型的玩家时会出现错误:
val footballTeam = Team(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
// ^^ is a Team<FootballPlayer> because of type inferrence.
footballTeam.addPlayers(BaseballPlayer("Foo")) // error, expected FootballPlayer
这里有一个泛型,但我不明白为什么即使我没有使类型 T 协变,我也可以将 Player 的子classes 添加到我的泛型中class 和具有上限 T 的函数:Player;那么为什么在不使用 out 关键字的情况下保留子类型;因此,我可以 - 错误地 - 将 BaseballPlayer 和 GamesPlayer 添加到足球队。 1
class Team<T : Player>(val name: String, private val players: MutableList<T>) {
fun addPlayers(player: T) {
if (players.contains(player)) {
println("Player: ${(player as Player).name} is already in the team.")
} else {
players.add(player)
println("Player: {(player as Player).name} was added to the team.")
}
}
}
open class Player(open val name: String)
data class FootballPlayer(override val name: String) : Player(name)
data class BaseballPlayer(override val name: String) : Player(name)
data class GamesPlayer(override val name: String) : Player(name)
val footballTeam = Team<Player>(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
val baseballPlayer = BaseballPlayer("Baseball Player")
val footballPlayer = FootballPlayer("Football Player")
val gamesPlayer = GamesPlayer("Games Player")
footballTeam.addPlayers(baseballPlayer)
footballTeam.addPlayers(footballPlayer)
footballTeam.addPlayers(gamesPlayer)
您在此行定义的可变列表:
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
不是 MutableList<FootballPlayer>
。它是一个 MutableList<Player>
,因为你没有指定它的类型,所以编译器使用类型推断来假设你想要一个 MutableList<Player>
来适合你的 Team<Player>
构造函数的构造函数参数。
因此,将任何类型的 Player
放入 MutableList<Player>
中都是有效的,因为它只能 return 类型 Player
的项目。它仍然是类型安全的。
如果您明确说明了类型,那将是一个编译错误:
val footballTeam = Team<Player>(
"Football Team",
mutableListOf<FootballPlayer>(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
//error, expected MutableList<Player>
)
或者,如果您在团队构造函数中省略了类型,它会假定您想要一个 Team<FootballPlayer>
,并且在尝试添加其他类型的玩家时会出现错误:
val footballTeam = Team(
"Football Team",
mutableListOf(FootballPlayer("Player 1"), FootballPlayer("Player 2"))
)
// ^^ is a Team<FootballPlayer> because of type inferrence.
footballTeam.addPlayers(BaseballPlayer("Foo")) // error, expected FootballPlayer