对于一个项目,我正在尝试实现一个Bit
类,该类可以完成所有通常的工作。
如果给定值为Number
,则构造函数应该能够使用任何Bit
并将0
的内部状态设置为0
,否则将其设置为{ {1}}。
所有方法都适用于整数输入,但是当我浮动时……显然1
不等于0.0
。
0
现在是问题:
class Bit(value: Number) {
var value: Int = (value != 0).toInt() // I implemented Bool-to-Int myself
}
我认为这是某种近似误差,但是当我尝试println(Bit(0).value) // Prints 0
println(Bit(0f).value) // Prints 1
时,我得到了print(0f != 0)
。但是,比较通过构造函数的数字没有问题。
我觉得这里有一些我不知道的隐藏的类型转换魔术,所以我的问题基本上是“为什么这不符合预期的行为,以及使它按预期的行为运行的一种优雅方法?” >
答案 0 :(得分:1)
我无法准确地告诉您为什么它的行为不如您预期,但是我可以给您一个简单的解决方法!
Number
接口虽然没有您想要的强大,但是它提供的主要功能是将其值转换为任何标准数值类型的一种方法。您可以这样使用:
class Bit(value: Number) {
var value = if (value.toDouble() == 0.0) 0 else 1
}
这将适用于所有Number
实现:Byte
,Double
,Float
,Int
,Long
,Short
,AtomicInteger
,AtomicLong
,BigDecimal
,Striped64
,以及您编写或导入的任何其他文件。
(无论您做什么,我建议您也覆盖value
的设置器,以确保它只保留0或1。)
答案 1 :(得分:1)
这与docs中所述的值表示形式被装箱有关。
您已经注意到,您无法比较不同的类型(当Float
和Int
用本机表示时)。但是您并没有这样做,而是使用了Number
类型。
考虑以下示例:
println(0.0f == 0) // error: Operator '==' cannot be applied to 'Float' and 'Int'
val n : Number = 0L // this forces value to be boxed
println(n == 0) // compiles and prints false
首先,编译器警告您无法执行比较。但是,如果将数值与对象一起装箱,则可以使用equalsTo
运算符。
只有当双方的类型和值都相同时,您会发现它返回true
。
不想在游行队伍中大吃一惊,但是实现类的正确方法是为每种数字类型声明单独的构造函数。这样可以防止编译器将值装箱,并让您正确地确定相等性:
class Bit constructor(value : Boolean) {
val value = if(value) 1 else 0
constructor(value : Int) : this(value == 0)
constructor(value : Float) : this(value == 0f)
constructor(value : Long) : this(value == 0L)
// etc
}