我试图赋予任何数字提升到任意权力的能力(具体来说,2)。这似乎是使用协议扩展而不是向Float
,Double
,Int
等添加扩展程序的绝佳机会。
protocol Raisable {
func raise(exponent : Self) -> Self
}
extension Raisable where Self : SignedNumberType {
func raise(exponent : Double) -> Self {
return Self(pow(Double(self), exponent))
}
}
protocol Squarable : Raisable {
func squared() -> Self
}
extension Squarable {
func squared() -> Self {
return self.raise(2)
}
}
编译器显示"找不到类型' Double'的初始值设定项。接受类型'(自我)'"。
的参数列表我有什么想法可以改变raise:
来解决这个问题吗?
提前致谢。
答案 0 :(得分:4)
这里有很多重叠的问题可能无法很好地解决(即使你这样做,结果也不会很好)。让我们来看看其中一些。
protocol Raisable {
func raise(exponent : Self) -> Self
}
好的,我们已经遇到了第一个问题。考虑Self
是否为Int
。 Int(2).raise(-1)
的结果是什么?它应该是0.5,但这不是整数。你打算圆到1吗?这与您为Double
编写的代码完全不同。
extension Raisable where Self : SignedNumberType {
func raise(exponent : Double) -> Self {
return Self(pow(Double(self), exponent))
}
}
这要求每个可能的SignedNumberType
可以转换为Double
,而不是承诺,甚至是可取的。SignedNumberType
。例如,复数满足pow
的所有要求,将复数提高到实数指数是合理的,但i^2
不是正确的函数。您确实需要使用差异化代码来处理这些情况。特别考虑i
的情况,这是真实的,所以只需将0
投影到其真实组件(extension Squarable {
func squared() -> Self {
return self.raise(2)
}
}
)上,然后进行平方,这将导致非常令人惊讶的结果。
self*self
除了其他问题之外,这非常非常缓慢(在适用的情况下比self<<1
或Double
慢几个数量级)。如果能够显着提高可读性,那就不是世界的终点,但它似乎并不是真的。
一般来说,Swift并不鼓励采用“一些数字,我不关心什么类型”的功能。在大多数情况下,您需要编写代码来处理数字转换,并考虑溢出,截断等情况。如果要将所有内容提升到squared()
,通常需要有意识地执行此操作,而不是通过协议。
但是这里还有一些关于扩展的知识。我们当然可以轻松地创建protocol Multipliable {
func *(lhs: Self, rhs: Self) -> Self
}
extension Multipliable {
func squared() -> Self {
return self * self
}
}
extension Int: Multipliable {}
extension Double: Multipliable {}
2.squared()
(2.1).squared()
方法并将其附加到各种类型。例如:
#!/bin/bash
# CHANGE THESE FOR YOUR APP
app_package="com.example"
dir_app_name="MySysApp"
MAIN_ACTIVITY="SysAppMainActivity"
ADB="adb" # how you execute adb
ADB_SH="$ADB shell" # this script assumes using `adb root`. for `adb su` see `Caveats`
path_sysapp="/system/priv-app" # assuming the app is priviledged
apk_host="./app/build/outputs/apk/app-debug.apk"
apk_name=$dir_app_name".apk"
apk_target_dir="$path_sysapp/$dir_app_name"
apk_target_sys="$apk_target_dir/$apk_name"
# Delete previous APK
rm -f $apk_host
# Compile the APK: you can adapt this for production build, flavors, etc.
./gradlew assembleDebug || exit -1 # exit on failure
# Install APK: using adb root
$ADB root 2> /dev/null
$ADB remount # mount system
$ADB push $apk_host $apk_target_sys
# Give permissions
$ADB_SH "chmod 755 $apk_target_dir"
$ADB_SH "chmod 644 $apk_target_sys"
#Unmount system
$ADB_SH "mount -o remount,ro /"
# Stop the app
$ADB shell "am force-stop $app_package"
# Re execute the app
$ADB shell "am start -n \"$app_package/$app_package.$MAIN_ACTIVITY\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER"