Почему скаляр выводит `Foo with Bar`, а не просто`Foo` для типа возврата совпадения / регистра?
В модельном классе у меня есть простой getter
функционировать так:
def geoLoc = {
geoQuant match {
case "COUNTRY" => Country.find.byId(geoLocId)
case "PROVICE" => Province.find.byId(geoLocId.toLong)
case "CITY" => City.find.byId(geoLocId.toLong)
case "STREET" => Street.find.byId(geoLocId.toLong)
}
}
Идея состоит в том, чтобы получить геолокацию объекта - который может быть любого из четырех типов. Из того, что я вижу, функция geoLoc
имеет тип возврата, который является суперклассом всех: Country
, Province
, City
& Street
- которые расширяют Model
учебный класс.
Вместо этого тип возвращаемого значения функции Model with GeoEntity
, где GeoEntity
это черта каждого из этих классов наряду с Model
,
Почему это происходит? Что я могу сделать, чтобы функция возвращала определенные типы с сопоставлением с образцом?
1 ответ
Скала выводит наиболее конкретный тип, который он может. Каждый из четырех экземпляров Model
и GeoEntity
Итак, это выводимый тип: Model with GeoEntity
, Если вы хотите, чтобы функция возвращала менее конкретный тип Model
(все Model with GeoEntity
с Model
с, но не все Models
являются Model with GeoEntity
s), просто аннотируйте функцию с этим типом: def geoLoc: Model = ...
,
Функция может иметь только один возвращаемый тип, и во время компиляции невозможно узнать, в какой из четырех случаев она попадет. Если вы хотите вернуть более конкретный тип для каждого случая, то информация о том, какой тип у этого объекта, должна быть частью типа объекта (или вы можете использовать зависимую типизацию, но информация о типе все равно должна откуда-то приходить), Например, вы можете сделать свой объект абстрактным универсальным типом с подклассами для конкретных экземпляров:
class MyObject[LocationType <: Model] {
def geoLoc: LocationType
}
class MyObjectCountry extends MyObject[Country] {
def geoLoc: Country = ...
}
class MyObjectProvice extends MyObject[Province] {
def geoLoc: Province = ...
}