Почему скаляр выводит `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 GeoEntitys), просто аннотируйте функцию с этим типом: 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 = ...
}
Другие вопросы по тегам