加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在List中使用自定义scala类型

发布时间:2020-12-16 09:48:59 所属栏目:安全 来源:网络整理
导读:我期待创建一个表示数据大小(字节,KB …)的类型系列.为此,我们的想法是建立一个基本类型,使其具有以下实际尺寸: type SizeUnit = Int type B = SizeUnit type KB = SizeUnit type MB = SizeUnit type GB = SizeUnit type TB = SizeUnit type PB = SizeUnit
我期待创建一个表示数据大小(字节,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的新手):

>有没有办法创建一个包含类型而不是值的List(或任何其他Seq)?或者更确切地说 – 类型作为值?
>如果我理解正确,类型不会超出编译范围.这是否意味着在运行时,如果我将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

类型别名只是同一类型的不同名称.所以即使你可以写它,你的列表也相当于写了:

val sizes = List(Int,Int,Int)

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

要将B,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兆字节是存储(3,MB),17字节是存储(17,B).您可以在任意整数和存储数量之间进行静态强制分离,并且只要有存储数量,就始终将单元作为数据对象(无需静态推断).您可以将对象B,MB等放在一个列表中,并根据需要对它们进行任何操作.

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

您甚至可以使用此方案通过隐式转换来处理古怪的事情.我想起这样的事情:

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,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 MB或123456789 B而不是存储(4,MB)或存储(123456789,B).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读