2013-12-03 2 views
0

Можно ли переопределить элементы внутреннего признака при расширении внешнего класса? КакВозможно переопределение элементов внутренней черты?

class Foo { 
    trait Bar { 
    def bar = Set("a", "b") 
    } 

    class Baz extends Bar 
    object Baz { 
    def apply() = new Baz 
    } 
} 

Могу ли я создать экземпляр f из Foo в любой форме, такой, что f.Baz().bar == Set("c", "d") к примеру?

Уточнение: Класс Foo является данным, я не могу его изменить. Он вызывает Baz(), поэтому я также не могу это изменить. Таким образом, вероятно, невозможно уточнить переопределения вещей в Bar или Baz?

ответ

0

Edit:

Основываясь на своем разъяснении, похоже, что вы хотите сделать, это переопределить объект Baz. Это обычно не возможно, но если вы используете экспериментальный флаг компилятора -Yoverride-objects, вы можете сделать следующее:

class SubFoo extends Foo { 
    class Baz extends super.Baz { 
    override def bar = Set("c", "d") 
    } 
    override object Baz { 
    def apply() = new Baz 
    } 
} 

С этой (new SubFoo).Baz().bar == Set("c", "d"). Однако, если ваш экземпляр подкласса введен как Foo, вы можете получить исключение класса класса выполнения, как в этой ошибке: SI-6525.

Оригинал Ответ:

Вы должны иметь Overridable фабричный метод в классе Foo, который может вернуть свой бар подкласс. Затем в подклассе Foo верните подкласс класса Bar с переопределенным методом. Например:

class Foo { 
    trait Bar { 
    def bar = Set("a", "b") 
    } 

    def createBar = new Bar {} 
} 

class SubFoo extends Foo { 
    override def createBar = new Bar { override def bar = Set("c", "d") } 
} 

scala> var foo: Foo = new Foo 
foo: Foo = [email protected] 

scala> foo.createBar.bar 
res15: scala.collection.immutable.Set[String] = Set(a, b) 

scala> foo = new SubFoo 
foo: Foo = [email protected] 

scala> foo.createBar.bar 
res16: scala.collection.immutable.Set[String] = Set(c, d) 
+0

Проблема в том, что 'Foo' является данным, я его не проектировал (на самом деле это часть структуры компилятора Scala). –

+0

Возможно, вы могли бы еще подробнее разъяснить ограничения. Я показал, как подклассировать внутреннюю черту при расширении внешнего класса. Однако, чтобы использовать подклассифицированный внутренний признак, вам необходимо создать его экземпляр. Если вы не можете переопределить код, который создает оригинальную черту с вашим новым признаком, вы действительно не можете сделать этого. Но это не имеет никакого отношения к тому, что это внутренняя черта. – kong

0

Вы можете создать новый класс, родитель которого является оригинальным Baz. Тогда переопределять бар:

val f = new Foo { 
    class Baz2 extends Bar { override def bar = Set("c") } 
    object Baz2 { 
    def apply() = new Baz2(); 
    } 
} 

Это даст вам новую запись: f.Baz2().bar, который даст вам Set («C»). У вас все равно будет доступ к членам оригинальной черты Bar.

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

+0

Проблема заключается в реализации 'Foo' создает экземпляр' Baz', поэтому он не заметит другого подкласса –

+0

. Я не уверен, что я следую ... Какой подкласс вы имеете в виду? В приведенной выше реализации вы получаете все исходные Baz, но с определенным методом переопределены. Можете ли вы уточнить, что вам нужно для работы? –