gpt4 book ai didi

scala - 在列表中使用自定义 Scala 类型

转载 作者:行者123 更新时间:2023-12-04 17:52:59 24 4
gpt4 key购买 nike

我希望创建一个表示数据大小(字节、KB...)的类型系列。为此,我们的想法是构建一个基本类型以具有基于以下条件的实际大小:

  type SizeUnit = Int
type B = SizeUnit
type KB = SizeUnit
type MB = SizeUnit
type GB = SizeUnit
type TB = SizeUnit
type PB = SizeUnit
type EB = SizeUnit
type ZB = SizeUnit
type YB = SizeUnit

有一个有序的列表:
val sizes = List(B, KB, MB, GB, TB, PB, EX, ZB, TB)

并有一个转换方法,它采用目标类型,找到它们之间的索引差,然后乘以 1024 的差幂。所以:
def convertTo(targetType: SizeUnit): SizeUnit ={
def power(itr: Int): Int = {
if (itr == 0) 1
else 1024*power(itr-1)
}

val distance = sizes.indexOf(targetType) - sizes.indexOf(this)
distance match {
//same type - same value
case 0 => targetType
//positive distance means larget unit - smaller number
case x>0 => targetType / power(distance)
//negative distance means smaller unit - larger number and take care of negitivity
case x<0 => targetType * power(distance) * (-1)
}
}

在检查方法的有效性之前,我遇到了一些问题(因为我是 Scala 的新手):
  • 有没有办法创建一个包含类型而不是值的列表(或任何其他序列)?或者更确切地说 - 类型作为值?
  • 如果我理解正确,类型不会超出编译范围。这是否意味着在运行时,如果我将 GB 值传递给现有的 KB,它无法破译类型?

  • 谢谢你,
    埃胡德

    最佳答案

    所有这些类型都只是类型别名,而不是独立类型。

    scala> type SizeUnit = Int
    defined type alias SizeUnit

    scala> type B = SizeUnit
    defined type alias B

    scala> type KB = SizeUnit
    defined type alias KB

    scala> (3 : KB) == (3 : B)
    res0: Boolean = true

    类型别名只是相同类型的不同名称。所以即使你能写出来,你的 list 也相当于写了:
    val sizes = List(Int, Int, Int, Int, Int, Int, Int, Int, Int)

    同样,您永远不能使用这些类型来编写需要接受以 MB 为单位的数量的函数,因为所有这些类型都是相同的。

    要将 B、KB、MB 等作为不同“种类”的整数分开,您需要它们是 Int 的子类型,而不是 Int 的类型别名。但是 Int 是最终类型,因此无论如何您都不能对其进行子类型化。

    一个更好的方法是让 Int 表示一个原始数字,而是实现一个表示 Int 和一个单元的类型。您可以采取多种方法,但我会这样做:
    abstract class SizeUnit

    case object B extends SizeUnit
    case object KB extends SizeUnit
    case object MB extends SizeUnit


    case class Storage(num : Int, unit : SizeUnit)

    现在 3 兆字节是 Storage(3, MB) ,17 字节是 Storage(17, B) 。您在任意整数和 Storage 数量之间有很好的静态强制分离,并且每当您有 Storage 数量时,您始终将单位作为数据对象(无需能够静态推断它)。您可以将对象 BKBMB 等放在一个列表中,然后对它们进行任何您想要的操作。

    或者,您可以使单元对象本身包含有关它们的顺序或它们之间的比率的一些信息,而不是将该信息存储在外部列表中。

    您甚至可以使用此方案通过隐式转换来做古怪的事情。这样的事情浮现在脑海:
    object SizeableInt {
    // since I want to give the conversion methods the same name as the
    // units, I need different names to refer to the units in the
    // implementation of those methods. If B, KB, etc were defined in
    // a different qualified namespace, this wouldn't be necessary.
    private val _B = B
    private val _KB = KB
    private val _MB = MB

    case class SizeableInt(x : Int) {
    def B : Storage = Storage(x, _B)
    def KB : Storage = Storage(x, _KB)
    def MB : Storage = Storage(x, _MB)
    }

    implicit def makeSizeableInt(x : Int) : SizeableInt = SizeableInt(x)
    }

    这样,一旦您导入了隐式,您就可以简单地编写 4 MB123456789 B 之类的东西,而不是 Storage(4, MB)Storage(123456789, B)

    关于scala - 在列表中使用自定义 Scala 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12963347/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com