2012-06-04 2 views
3

Я пытаюсь определить признак, который использует соответствующий объект-компаньон, то есть объект-компонент класса с использованием признака.scala: определение признака и ссылка на соответствующий объект-компаньон

, например, у меня есть:

:paste 

class Parent { 
    def callMyCompanion = print(Parent.salute) 
} 

object Parent { 
    def salute = "Hello from Parent companion object" 
} 

class Child extends Parent { 

} 

object Child { 
    def salute = "Hello from Child companion object" 
} 

А затем создать родительский объект:

scala> val p = new Parent() 
p: Parent = [email protected] 

scala> p.callMyCompanion 
Hello from Parent companion object 

Но с ребенком:

scala> val c = new Child() 
c: Child = [email protected] 

scala> c.callMyCompanion 
Hello from Parent companion object 

Я хотел бы получить : Hello from Child companion object

Как я могу это достичь ???

- редактирование уточнить

Спасибо за ваши ответы, но в этом случае callMyCompanion фиктивный метод, который я создал только объяснить себе, я пытаюсь повторно родительский метод без необходимости заменить его во всех класс, который реализует его ...

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

+0

Почему вы не переопределяете метод 'callMyCompanion' в классе' Child'? –

+0

Я отредактировал вопрос, чтобы уточнить, что – opensas

+0

Каков ваш конкретный прецедент? Может ли это быть лучше с помощью типов? – drexin

ответ

2

Этот запрос равносилен статического переопределения. Такая вещь не существует в scala, AFAIK, но вы можете включить переопределение метода экземпляра в Child, который будет называть его сопутствующим объектом для сообщения. Что-то говорит мне, что ты не хочешь этого делать.

+0

вы правы, я только что отредактировал вопрос, чтобы уточнить, что – opensas

5

Решение, которое я нашел до сих пор было добавить ссылку на объект компаньона в классе, так что каждая переменная экземпляра может получить собеседницы объект своего класса

Таким образом, у меня есть только переопределить метод, чтобы получить ссылку на объект компаньон ...

для этого мне пришлось реализовать ParentCompanion черту ...

Но мне не нужно, чтобы переопределить callMyCompanion, или любой другой метод, требуется доступ к сопутствующему объекту.

Это все было бы гораздо проще, если бы я мог получить ссылку на объект компаньона через отражение ...

код что-то вроде этого

:paste 

trait ParentCompanion { 
    def salute: String 
} 

class Parent { 
    def callMyCompanion = print(companion.salute) 
    def companion: ParentCompanion = Parent 
} 

object Parent extends ParentCompanion { 
    def salute = "Hello from Parent companion object" 
} 

class Child extends Parent { 
    override def companion = Child 
} 

object Child extends Companion { 
    def salute = "Hello from Child companion object" 
} 
1

Основная проблема с фактически имеющих доступ к объект-компаньон, не зная, какой он есть, заключается в том, что у вас в основном есть только AnyRef, что совсем не очень полезно.

Другим подходом было бы использовать структурную типизацию. Я предполагаю, что все ваши разные объекты-компаньоны будут иметь что-то общее (например, salute, которые вы захватили в своем значении ParentCompanion). После этого вы можете сделать следующее:

class Parent { 
    val companion : { 
    def salute : String 
    } = Parent 
    def foo = println(companion.salute) 
} 
object Parent { 
    val salute = "Parent Companion" 
} 
class Child extends Parent { 
    override val companion = Child 
} 
object Child { 
    val salute = "Child Companion" 
} 

Учитывая это, каждый суб-класс может переопределить атрибут companion, чтобы указать на соответствующий объект компаньона, если он удовлетворяет структурный тип, приведенный в Parent (т.е.в этом случае он должен иметь salute). И вы можете вызвать этот метод на вашем спутнику, как это:

scala> (new Parent).foo 
Parent Companion 

scala> (new Child).foo 
Child Companion 
3

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

trait Greeter[T] { 
    def salute: Unit 
} 
object Greeter { 
    implicit def anyToGreeter[A](x: A) = new { 
    def salute(implicit greeter: Greeter[A]) = greeter.salute 
    } 
} 

class Foo 
class Bar extends Foo 

implicit object FooGreeter extends Greeter[Foo] { 
    def salute = println("Hello from FooGreeter.") 
} 
implicit object BarGreeter extends Greeter[Bar] { 
    def salute = println("Hello from BarGreeter.") 
} 

С этим я получаю следующее выход:

scala> import Greeter._ 
import Greeter._ 

scala> new Foo().salute 
Hello from FooGreeter. 

scala> new Bar().salute 
Hello from BarGreeter. 
+0

Спасибо, хороший пример, но мне сложно сдерживать все эти импликации. Если я правильно понимаю, после решения каждого неявного, компилятор выпускает: anyToGreeter [Foo] (новый Foo()). Salute (FooGreeter) ... Я прав? – opensas

+0

Да, это правильно. – drexin

+0

К сожалению: val x: Foo = new Bar; x.salute - это не то, что вы можете надеяться. – user48956

Смежные вопросы