2012-02-07 21 views
10

Amacım, bir özellik karma kullanımı kullanarak varolan bir Java sınıfını iç scala kodunun geliştirilmesidir. Örneğin java.awt.Rectangle.translate (dx, dy) gibi java.awt.geom.Ellipse2D sınıfına bir yöntem eklemek. bir elips oluştururkenjava sınıflarını, özellikleri kullanarak, java alanlarının içerisine nasıl bildirileceğini geliştirin?

trait RectangleLike { 
    var x: Double // abstract vals to correspond to java class fields 
    var y: Double // I need these vars to refer to them inside translate method 
    def translate(dx: Double, dy: Double) { 
    x = x + dx 
    y = y + dy 
    } 
    // more concrete trait methods here 
} // defines without errors in scala REPL 

Sonra özelliği kullanmak: Bunun için aşağıdaki özelliği oluşturmak

: Ancak

val egg = new java.awt.geom.Ellipse2D.Double(5, 10, 20, 30) with RectangleLike 

ben scala repl yukarıdaki komut dosyası çalıştırdığınızda aşağıdaki çıktıyı almak

<console>:8: error: overriding variable x in trait RectangleLike of type Double; 
variable x in class Double of type Double has incompatible type; 
other members with override errors are: y 
val egg = new java.awt.geom.Ellipse2D.Double(5, 10, 20, 30) with RectangleLike 

Bu hatanın Scala'nın özel bir alan ve bir alıcı/ayarlayıcı yöntem çifti olarak varsayı uygulamasından kaynaklandığından şüpheleniyorum. Yapılabilirliği başarmaya çalıştığım şey mi? Java sınıfı alanlarını özellikte tanımlamanın ve sonra bunları beton özellik metotları içinde ifade etmenin başka bir yolu var mıdır? peşin

Teşekkür Jack Dimas

cevap

8

Evet, yapılabilir ama bunun yerine, olur (zaten büyük olasılıkla kötü bir fikirdir) ile karıştırmak isteyen sınıfların özel alanları erişmeye çalışırken RectangleLike türünün kendi türünü java.awt.geom.RectangularShape olarak bildirmek istediğinizde, örneğin Ellipse2D.Double sadece Rectangle2D.Double ile. Burada nasıl çalışır

geçerli:

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 
} 

Eğer gerekli Alıcı ve ayarlayıcıların gibi tüm ilgili yöntemlerine erişmek sağlayan sizin özelliğin kendini türü bildirmek self: java.awt.geom.RectangularShape => derken, ile nitelik kullanılarak sağlar RectangularShape'un tüm soyundan gelenler, ve aynı zamanda, sadece kendi kendilerini RectangularShape alt türlerine sahip olan sınıflara bir karıĢım olarak kullanılabilecek şekilde özelliğinizi “kısıtlar”. Yukarıdaki senaryoya

alternatif

yanı ortak bir paradigma senin RectangularShape bir sözde görünümü kullanıyor. Bunun için ör. Bir sınıf

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 örtülü başka türde bir nesne olarak bir türdeki bir nesnenin inceleyen bir yolu vardır beyan ederim. Karşılık gelen türde bildirilmemiş bir nesne üzerinde bir yöntem çağırırsanız, derleyici bu yöntemi sağlayan bir tür bulmak ve özellikle de özgün nesnenin bir nesne olarak görülebilmesi için örtülü bir dönüşüm bulmak için trys ikinci tipin örneği. Bu işlemin gerçekleşmesi için, genellikle böyle bir şey olarak RichRectangularShape tamamlayıcı nesnesi ilan edeceğini: Sonra

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 
+1

@forNelton etkileyici! Teşekkürler mil gerçekten bunun üzerinde sıkışmış. Örtülü görüşlerini incelemek zorundayım. – ideathbird

+0

Rica ederim. Uygulamanızın türüne bağlı olarak, ilk yaklaşımın daha uygun olabileceğini düşünüyorum çünkü yöntem çağrıları, tüm örtülü güçlükler olmadan daha hızlı olabilir. – fotNelton

0

Nitekim etkileyici açıklama ve örnek!

Bu yaklaşımla ilgili küçük bir sorunum var; translate yöntemi, kaçınmak istediğiniz gerçek hesaplamayı içerir. Evet bu durumda çok basit ama genel olarak böyle bir yöntem karmaşık olabilir ve ciddi gelişime yol açabilir.Ben orijinal translate hesaplama kullanıyorum Bu şekilde

trait RectangleLike extends java.awt.geom.RectangularShape { 
    def translate(dx: Int, dy: Int): Unit = { 
     val rect = new java.awt.Rectangle 
     rect.setRect(getX, getY, getWidth, getHeight) 
     rect.translate(dx,dy) 
     setFrame(rect.getX, rect.getY, rect.getWidth, rect.getHeight) 
     } 
} 

: Bu yüzden aşağıdaki yaklaşımı göstermektedir.