Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

371
Visualizações
How do I reuse a T::Struct structure in another T::Struct

I have the following:

class Coordinate < T::Struct
  const :x, Integer
  const :y, Integer
end

class ThreeDCoordinate < T::Struct
  const :x, Integer
  const :y, Integer
  const :z, Integer
end

What I want is to have my ThreeDCoordinate inherit x and y of Coordinate so I don't have to rewrite them in ThreeDCoordinate. How can I accomplish this?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

There is a way to do this, using T::InexactStruct, but you will have to give up being able to strongly type the initializer of your structs:

# typed: true

class Coordinate < T::InexactStruct
  const :x, Integer
  const :y, Integer
end

class ThreeDCoordinate < Coordinate
  const :z, Integer
end


coord = Coordinate.new(x: 2, y: 3)
T.reveal_type(coord.x)
T.reveal_type(coord.y)

threeD = ThreeDCoordinate.new(x: 2, y: 3, z: 4)
T.reveal_type(threeD.x)
T.reveal_type(threeD.y)
T.reveal_type(threeD.z)

# Note that the constructors are not typed anymore:
Coordinate.new(x: "foo", y: :bar) # This should fail but doesn't

Sorbet Playground Link

The problem with T::Struct and subclassing is that Sorbet creates an initializer for your struct that takes into account all of its declared fields. So for Coordinate the initializer has the signature params(x: Integer, y: Integer).void but for ThreeDCoordinate it has the signature params(x: Integer, y: Integer, z: Integer).void. Now these signatures are not compatible with each other, so Sorbet does not allow you to subclass one from the other.

T::InexactStruct allows you to give up the strong typing in the constructor and trade it in for being able to do inheritance on typed structs.

over 4 years ago · Santiago Trujillo Relatório

0

As far as I know, Sorbet does not support exactly the feature that you asked.

However, I am using interfaces to achieve similar typing goals:

module Coordinate
  extend T::Helpers
  extend T::Sig

  interface!

  sig { abstract.returns(Integer) }
  def x; end

  sig { abstract.returns(Integer) }
  def y; end
end

module ThreeCoordinate
  extend T::Helpers
  extend T::Sig

  include Coordinate

  interface!

  sig { abstract.returns(Integer) }
  def z; end
end

class ThreeDLocation < T::Struct
  extend T::Sig
  
  include ThreeCoordinate
  
  # Will be complained by Sorbet because of missing interface
  const :x, Integer
end

class ThreeDCenter < T::Struct
  extend T::Sig

  include ThreeCoordinate

  sig { override.returns(Integer) }
  def x
    0
  end

  sig { override.returns(Integer) }
  def y
    0
  end

  sig { override.returns(Integer) }
  def z
    0
  end
end

Try out on Sorbet Playground to see how Sorbet static checks help ensure the typing.

Although there might be some repetitions in the codes, we have achieved the goal that classes implementing ThreeCoordinate is guaranteed to have the interface of Coordinate as well.

Also, using this approach, the implementation is more flexible. We can also implement something like ThreeDCenter above without being tied down to using Struct properties only.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda