我有两个类:1.分数类:分子和分母与2. 2. OperationWithFractions类执行类似于将两个分数相加的计算,并将结果表示为String分数(例如32/5)。
它可以工作,但是我想通过将两个类合并为一个来简化,因此所有属性,方法和初始化程序都将在同一伞下。
class Fraction {
var numerator = 0
var denominator = 0
init (_ numer: Int, _ denom: Int){
self.numerator = numer
self.denominator = denom
}
}
class OperationWithFractions {
var fraction1: Fraction
var fraction2: Fraction
init(_ fraction1: Fraction, _ fraction2: Fraction) {
self.fraction1 = fraction1
self.fraction2 = fraction2
}
func addFractions()->String {
var result = ""
result = "\(fraction1.numerator * fraction2.denominator + fraction1.denominator * fraction2.numerator) / \(fraction1.denominator * fraction2.denominator)"
return result
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let result = OperationWithFractions(Fraction(5, 10), Fraction(10, 20)).addFractions()
print(result)
let result2 = OperationWithFractions(Fraction(10, 2), Fraction(8, 2)).addFractions()
print(result2)
}
}
答案 0 :(得分:3)
两个分数相加应返回一个Fraction
,而不是字符串。转换
仅当需要文本表示形式(例如,打印最终结果)时,才将字符串转换为字符串。
算术运算可以作为运算符 分数类型:
struct Fraction {
// ...
static func +(lhs: Fraction, rhs: Fraction) -> Fraction { ... }
}
那可以让你写
let result = Fraction(1, 2) + Fraction(-1, 6)
相对于引用类型和常量属性,它们也更喜欢值类型 超过可变属性。第一个实现可能是
struct Fraction {
let numerator: Int
let denominator: Int
init (_ numer: Int, _ denom: Int) {
self.numerator = numer
self.denominator = denom
}
static func +(lhs: Fraction, rhs: Fraction) -> Fraction {
return Fraction(lhs.numerator * rhs.denominator + lhs.denominator * rhs.numerator,
lhs.denominator * rhs.denominator)
}
}
采用CustomStringConvertible
协议来提供
文字表示形式:
extension Fraction: CustomStringConvertible {
var description: String {
return "\(numerator)/\(denominator)"
}
}
这已经有效
// Compute 1/2 - 1/6 + 1/3:
let result = Fraction(1, 2) + Fraction(-1, 6) + Fraction(1, 3)
print(result) // 24/36
,但结果并不完全令人满意,因为 不简化为最低的通用术语。也是
print(Fraction(2, -3)) // 2/-3
不是最佳选择。
这里是一个稍微复杂一些的版本,
结果降低到最低的条件。除了
gcd
实用程序功能,所有内容都在
Fraction
类型。
// Greatest common divisor
func gcd(_ a : Int, _ b : Int) -> Int {
var (a, b) = (a, b)
while b != 0 {
(a, b) = (b, a % b)
}
return a
}
struct Fraction {
let numerator: Int
let denominator: Int
init (_ numer: Int, _ denom: Int, reduce: Bool = false) {
if reduce {
let commonFactor = gcd(numer, denom)
self.numerator = numer / commonFactor
self.denominator = denom / commonFactor
} else {
self.numerator = numer
self.denominator = denom
}
}
static func +(lhs: Fraction, rhs: Fraction) -> Fraction {
return Fraction(lhs.numerator * rhs.denominator + lhs.denominator * rhs.numerator,
lhs.denominator * rhs.denominator, reduce: true)
}
}
extension Fraction: CustomStringConvertible {
var description: String {
if denominator == 1 {
return "\(numerator)"
} else if denominator < 0 {
return "\(-numerator)/\(-denominator)"
} else {
return "\(numerator)/\(denominator)"
}
}
}
用法示例:
// Compute 1/2 - 1/6 + 1/3:
let result = Fraction(1, 2) + Fraction(-1, 6) + Fraction(1, 3)
print(result) // 2/3
现在您可以添加其他运算符(例如-
,*
,/
),错误检查
(例如分母为零或整数溢出),其他实例方法(例如“绝对值”)等。
答案 1 :(得分:2)
Makefile
现在,这是怎么回事?
我将整个分数类转换为$ ls
Makefile test.c
$ cat Makefile
libTest.a: libTest.a(test.o)
$(AR) $(ARFLAGS) $@ $?
$ make
`libTest.a' is up to date.
$ ls
Makefile test.c
,因为它仅用于格式化输入数据。
接下来,我将您的class OperationWithFractions {
typealias Fraction = (numerator: Int, denominator: Int)
private let fraction1: Fraction
private let fraction2: Fraction
init(_ fraction1: Fraction, _ fraction2: Fraction) {
self.fraction1 = fraction1
self.fraction2 = fraction2
}
func addFractions() -> String {
return "\(fraction1.numerator * fraction2.denominator + fraction1.denominator * fraction2.numerator) / \(fraction1.denominator * fraction2.denominator)"
}
}
let fraction1 = OperationWithFractions.Fraction(numerator: 1, denominator: 2)
let fraction2 = OperationWithFractions.Fraction(numerator: 2, denominator: 3)
let operation = OperationWithFractions(fraction1, fraction2)
print(operation.addFractions()) // 7/6
替换为typealias
。这封装了只有您的类需要的逻辑。
init函数不变。
最后,由于不需要设置初始变量和单独的收益,因此我清理了您的收益。
也可以只创建一个接受num1,den1,num2,den2等的初始化程序,但是如果要添加3个或更多的分数,这将无法很好地扩展。
答案 2 :(得分:1)
您似乎想避免在两个类中都定义两个属性和初始化程序。这很容易;只需使用泛型,例如
class MathematicalOperation<T> { // you can limit T to numerics, but there's no advantage here
var firstOperand: T
var secondOperand: T
init (_ first: T, _ second: T){
firstOperand = first
secondOperand = second
}
}
然后,您可以将此子类化为Fraction
和OperationWithFractions
子类:
class Fraction: MathematicalOperation<Int> {
// no need to define another initializer or properties
}
class OperationWithFractions: MathematicalOperation<Fraction> {
func addFractions()->String {
return "\(firstOperand.firstOperand * secondOperand.secondOperand + firstOperand.secondOperand * secondOperand.firstOperand) / \(firstOperand.secondOperand * secondOperand.secondOperand)"
}
}
但是,这显然不理想,因为firstOperand.firstOperand
,secondOperand.firstOperand
等不是很清楚。 问题就在其中:您正试图为自己节省一些写作时间,但是在此过程中,您混淆了要解决的问题,因为必须选择一个足够通用的名称对于属性。在这种情况下,这样做似乎并不值得。您可能会比以前更好,因为该属性为 meant 命名。