Да, это выполнимо, но вместо того, чтобы пытаться получить доступ к закрытым полям классов, с которыми вы хотите смешаться (что, скорее всего, плохая идея в любом случае), вы захотите объявить собственный тип RectangleLike
быть java.awt.geom.RectangularShape
, чтобы вы могли использовать свою черту, например, с Ellipse2D.Double
так же, как и с Rectangle2D.Double
.
Вот как это работает:
trait RectangleLike {
self: java.awt.geom.RectangularShape =>
def translate(dx: Double, dy: Double) {
setFrame(getX + dx, getY + dy, getX + getWidth, getY + getHeight)
}
}
object Test {
val foo = new java.awt.geom.Ellipse2D.Double with RectangleLike
}
Говоря self: java.awt.geom.RectangularShape =>
, вы объявляете собственный тип вашей черты, который дает вам доступ ко всем соответствующим методам, таким как необходимые методы получения и установки, позволяет использовать эту черту со всеми потомками RectangularShape
, а также «ограничивает» Ваша черта, так что он может быть использован только как миксин для классов, которые сами являются подтипами RectangularShape
.
альтернатива вышеприведенному сценарию использует так называемое представление вашего RectangularShape
, которое также является общей парадигмой. Для этого вы бы, например, объявить класс
class RichRectangularShape(shape: java.awt.geom.RectangularShape) {
def translate(dx: Double, dy: Double) {
shape.setFrame(shape.getX + dx, shape.getY + dy,
shape.getX + shape.getWidth, shape.getY + shape.getHeight)
}
}
Scala имеет способ неявного просмотра объекта одного типа как объекта другого типа. Если вам случится вызвать метод для объекта, который не был объявлен в соответствующем типе, компилятор попытается найти тип, который предоставляет этот метод, и, в частности, также попытается найти неявное преобразование, чтобы ваш исходный объект мог рассматриваться как Экземпляр последнего типа. Чтобы это работало, вы обычно объявляете объект-компаньон RichRectangularShape
примерно так:
object RichRectangularShape {
implicit def mkRRS(shape: java.awt.geom.RectangularShape): RichRectangularShape =
new RichRectangularShape(shape)
}
Тогда:
scala> import RichRectangularShape._
import RichRectangularShape._
scala> val foo = new java.awt.geom.Ellipse2D.Double
foo: java.awt.geom.Ellipse2D.Double = java.awt.geom.Ellipse2D$Double@0
scala> foo.translate(5,2)
scala> foo.getX
res1: Double = 5.0
scala> foo.getY
res2: Double = 2.0
scala> :t foo
java.awt.geom.Ellipse2D.Double