Внедрить наследование класса класса в именах искры и столбца [дубликат]

Кажется, что с operator.add возникает путаница! Когда вы добавляете два списка вместе, правильным термином для этого является concat, а не добавлять. operator.concat - это то, что вам нужно использовать.

Если вы думаете о функциональности, это так же просто, как это ::

>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

. Вы видите, что уменьшают уважение к типу последовательности, поэтому, когда вы поставляете кортеж, вы возвращаете кортеж. давайте попробуем со списком ::

>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Aha, вы получите список.

Как насчет производительности ::

>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

from_iterable довольно быстро! Но это не сравнимо с уменьшением с concat.

>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
75
задан Andrea 3 October 2012 в 10:13
поделиться

4 ответа

Мой предпочтительный способ избежать наследования класса case без дублирования кода несколько очевиден: создать общий (абстрактный) базовый класс:

abstract class Person {
  def name: String
  def age: Int
  // address and other properties
  // methods (ideally only accessors since it is a case class)
}

case class Employer(val name: String, val age: Int, val taxno: Int)
    extends Person

case class Employee(val name: String, val age: Int, val salary: Int)
    extends Person

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

trait Identifiable { def name: String }
trait Locatable { def address: String }
// trait Ages { def age: Int }

case class Employer(val name: String, val address: String, val taxno: Int)
    extends Identifiable
    with    Locatable

case class Employee(val name: String, val address: String, val salary: Int)
    extends Identifiable
    with    Locatable
95
ответ дан Malte Schwerhoff 27 August 2018 в 22:25
поделиться
Классы классов

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

Но реализация equals в присутствии наследования довольно сложна. Рассмотрим два класса:

class Point(x : Int, y : Int)

и

class ColoredPoint( x : Int, y : Int, c : Color) extends Point

Таким образом, согласно определению ColorPoint (1,4, красный) должен быть равен Точке (1,4 ) они в то же время суть. Таким образом, ColorPoint (1,4, синий) также должен быть равен Point (1,4), правильно? Но, конечно, ColorPoint (1,4, красный) не должен совпадать с ColorPoint (1,4, синий), потому что они имеют разные цвета. Там вы идете, одно основное свойство отношения равенства сломано.

update

Вы можете использовать наследование от признаков, решающих множество проблем, как описано в другом ответе. Еще более гибкой альтернативой часто является использование классов типов. См. . Каковы классы типов в Scala, которые полезны для? или http://www.youtube.com/watch?v=sVMES4RZF-8

12
ответ дан Community 27 August 2018 в 22:25
поделиться

Поскольку это интересная тема для многих, позвольте мне пролить свет здесь.

Вы можете пойти по следующему подходу:

// You can mark it as 'sealed'. Explained later.
sealed trait Person {
  def name: String
}

case class Employee(
  override val name: String,
  salary: Int
) extends Person

case class Tourist(
  override val name: String,
  bored: Boolean
) extends Person

Да, вам нужно дублировать поля. Если вы этого не сделаете, было бы невозможно реализовать правильное равенство среди других проблем .

Однако вам не нужно дублировать методы / функции.

Если дублирование нескольких свойств очень важно для вас, используйте обычные классы, но помните, что они плохо подходят FP.

В качестве альтернативы вы могли бы использовать композицию вместо наследования:

case class Employee(
  person: Person,
  salary: Int
)

// In code:
val employee = ...
println(employee.person.name)

. Композиция - это правильная и звуковая стратегия, которую вы также должны учитывать.

И если вы задаетесь вопросом, что означает запечатанный признак - это то, что может быть расширен только в том же файле. То есть, два класса классов выше должны быть в одном файле. Это позволяет выполнять исчерпывающие проверки компилятора:

val x = Employee(name = "Jack", salary = 50000)

x match {
  case Employee(name) => println(s"I'm $name!")
}

Дает ошибку:

warning: match is not exhaustive!
missing combination            Tourist

Что действительно полезно. Теперь вы не забудете иметь дело с другими типами Person s (люди). Это, по сути, класс Option в Scala.

Если это не имеет для вас значения, вы можете сделать его незапечатанным и бросить классы case в свои собственные файлы. И, возможно, пойти с композицией.

38
ответ дан Kai Sellgren 27 August 2018 в 22:25
поделиться

В этих ситуациях я склонен использовать композицию вместо наследования. i .e.

sealed trait IVehicle // tagging trait

case class Vehicle(color: String) extends IVehicle

case class Car(vehicle: Vehicle, doors: Int) extends IVehicle

val vehicle: IVehicle = ...

vehicle match {
  case Car(Vehicle(color), doors) => println(s"$color car with $doors doors")
  case Vehicle(color) => println(s"$color vehicle")
}

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

4
ответ дан user 27 August 2018 в 22:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: