Ответ 1
Да, это выполнимо, но вместо того, чтобы пытаться получить доступ к закрытым полям классов, с которыми вы хотите смешать (что, скорее всего, будет плохой идеей), вы хотели бы объявить тип типа 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
, а также "ограничивает", ваш признак, чтобы его можно было использовать только как mixin для классов, которые сами являются подтипами 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 = [email protected]
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