Ссылка на тип, определенный в параметрах типа

#scala #generics #types

#scala #общие #типы

Вопрос:

Я пытаюсь создать систему обмена сообщениями, безопасную для типов. На данный момент лучшее, что я придумал, это:

 trait Component
trait Message[From <: Component, -To <: Handler[From]]

trait Handler[From <: Component]{
  type MessageType <: Message[From, this.type]

  def handle(message: MessageType): Unit;
}
 

Я бы хотел чего-то большего, чем это:

 trait Component
trait Message[From <: Component, -To <: Handler[From]]

trait Handler[From <: Component, MessageType <: Message[From, this.type]]{

  def handle(message: MessageType): Unit;
}
 

но компилятор жалуется на использование this.type в параметрах типа. Есть ли какой-нибудь способ для меня сослаться на тип, который я определяю в параметрах типа, чтобы я мог использовать синтаксис, который мне нравится?

Очевидно, что система типов может делать то, что я хочу, я бы просто хотел, чтобы она использовала синтаксис, который мне нравится.

—РЕДАКТИРОВАТЬ—

Я думаю, что нашел решение.

 trait Component
trait Message[From <: Component, 
              To <: Handler[From, To, MessageType], 
              MessageType <: Message[From, To, MessageType]]

trait Handler[From <: Component, 
              To <: Handler[From, To, MessageType], 
              MessageType <: Message[From, To, MessageType]]{

  def handle(message: MessageType ): Unit;
}
 

Немного более подробный в параметрах типа, но он работает хорошо.

Ответ №1:

Я не думаю, что вам нужны MessageType параметры типа для достижения того, чего вы хотите. Вместо этого сделайте MessageType равным Message[From, this.type] .

 trait Handler[From <: Component] {
  type MessageType = Message[From, this.type]

  def handle(message: MessageType): Unit;
}
 

Подумайте о том, чтобы сделать сообщение ковариантным в его первом параметре.

Обратите this.type внимание, что это не относится к определяемому вами типу. this.type это тип, который имеет только одно значение: this . this не существует вне тела признака и, следовательно, не может использоваться в параметрах типа. Если вам действительно нужно ссылаться на тип, в который будет смешан признак, вам нужен F-ограниченный полиморфизм.

Комментарии:

1. Итак, проблема с этим решением заключается в том, что вы не можете использовать подтип Message[From, this.type] в качестве параметра для обработки, что делает его гораздо менее полезным для сопоставления с образцом.

2. @Meshelton я не понимаю, что вы имеете в виду. Вы определенно можете передать подтип handle , методы всегда контравариантны по своим параметрам.

3. вы можете передать подтип, но вы не можете объявить метод таким def handle(message: SubtypeOfMessageType): Unit образом, вы получаете ошибку компилятора, которая имеет смысл.