Предположим, что у меня есть следующий код:
trait Trait1 {
trait Inner {
val name = "Inner1"
}
}
trait Trait2 {
trait Inner {
val name = "Inner2"
}
}
class Foo extends Trait1 with Trait2 {
// I want Concrete1 to be a Trait1.Inner not a Trait2.Inner
class Concrete1 extends Inner
val c = new Concrete1
}
object Obj {
def main(args: Array[String]): Unit = {
val foo = new Foo
println(foo.c.name)
}
}
Когда я смешиваюсь в Trait1
и Trait2
, обращение к Inner
кажется, принимает значение по умолчанию к Inner
тип какой бы ни черта я смешивающийся второй; таким образом, когда я звоню Obj
main
метод это печатает Inner2
. Как я могу обратиться к Trait1.Inner
в Foo
? Все три из следующего дают ошибки компилятора:
class Concrete1 extends Trait1.Inner
class Concrete1 extends Trait1$Inner
class Concrete1 extends Trait1#Inner
Вместо
class Concrete1 extends Inner
используют это
class Concrete1 extends super[Trait1].Inner
, что должно получить то, что вы хотите
В качестве альтернативы, Вы также можете попробовать StartSwarm. Я взял его и запустил, используя QUnit, чтобы запустить мои тесты JS.
-121--963343- Тег < br >
будет вставлен после конца каждого элемента < a >...
:
from BeautifulSoup import BeautifulSoup, Tag
# ....
soup = BeautifulSoup(data)
for a in soup.findAll('a'):
a.parent.insert(a.parent.index(a)+1, Tag(soup, 'br'))
Вы не можете использовать soup.findAll (tag = '')
, поскольку
Если вы хотите поместить элементы < a >
в элемент < p >
по запросу в комментарии, вы можете использовать следующее:
for a in soup.findAll('a'):
p = Tag(soup, 'p') #create a P element
a.replaceWith(p) #Put it where the A element is
p.insert(0, a) #put the A element inside the P (between <p> and </p>)
Опять же, вы не создаете элементы < p >
и
В шаблоне имеются два пространства имен (шаблон является телом класса, объекта или признака.)
При наследовании из нескольких родительских шаблонов конфликты в этих пространствах имен разрешаются посредством класса linases
Вы можете изменить порядок наследования, чтобы ввести в свой класс нужного родителя Inner, или найти альтернативный дизайн.
Один вариант (если вы можете быть инвазивными К чертам) состоит в том, чтобы определить каждую внутреннюю черту как член типа, который имеет неконфудирующее имя.
trait Trait1 {
type Inner1 = Inner
trait Inner {
val name = "Inner1"
}
}
trait Trait2 {
type Inner2 = Inner
trait Inner {
val name = "Inner2"
}
}
class Foo extends Trait1 with Trait2 {
class Concrete1 extends Inner1
class Concrete2 extends Inner2
val c1 = new Concrete1
val c2 = new Concrete2
}
object App extends Application {
val foo = new Foo
println(foo.c1.name) // Inner1
println(foo.c2.name) // Inner2
}
Если вы не можете быть инвазивными для оригинальных черт (Trait1 и Trait2), вы можете расширить их для определения элемента типа.
trait Trait1 {
trait Inner {
val name = "Inner1"
}
}
trait Trait2 {
trait Inner {
val name = "Inner2"
}
}
trait Trait1a extends Trait1 {
type Inner1 = Inner
}
trait Trait2a extends Trait2 {
type Inner2 = Inner
}
class Foo extends Trait1a with Trait2a {
class Concrete1 extends Inner1
class Concrete2 extends Inner2
val c1 = new Concrete1
val c2 = new Concrete2
}
Другой подход будет использовать промежуточную черту для определения вашего первого конкретного класса:
trait Trait1 {
trait Inner {
val name = "Inner1"
}
}
trait Trait2 {
trait Inner {
val name = "Inner2"
}
}
trait FooIntermediate extends Trait1 {
class Concrete1 extends Inner
}
class Foo extends FooIntermediate with Trait2 {
class Concrete2 extends Inner
val c1 = new Concrete1
val c2 = new Concrete2
}
Почему бы не заказать черт в том порядке, чтобы вы ожидаете их иметь приоритет? Линеаризация чертов не является произвольным, но указана.