我们假设我们有两个类Expense1
和Expense2
。哪个类实现比另一个更受欢迎,或者被认为更接近于面向对象?
我一直认为做Exp2.Calculate(1.5M,2)
比读取更可读
exp1.Calculate()
并使用exp1 Class的属性作为calculate方法的必需值。
Expense1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Expense1
{
public decimal ExpenseValue { get; set; }
public int NumberOfItems { get; set; }
private decimal result;
public decimal Result
{
get
{
return this.NumberOfItems * this.ExpenseValue;
}
}
public void Calculate()
{
this.result = this.ExpenseValue * this.NumberOfItems;
}
public void expense1()
{
this.ExpenseValue = 0;
this.NumberOfItems = 0;
}
}
Expense2
class Expense2
{
public decimal Calculate(decimal expenseValue, int numberOfItems)
{
return expenseValue * numberOfItems;
}
}
两个类的实施
class Program
{
static void Main(string[] args)
{
Expense1 exp1 = new Expense1();
exp1.NumberOfItems = 2;
exp1.ExpenseValue = 1.5M ;
exp1.Calculate();
Console.WriteLine("Expense1:" + exp1.Result.ToString());
Expense2 exp2 = new Expense2();
string result = string.Empty;
result = exp2.Calculate(1.5M,2).ToString();
Console.WriteLine("Expense2:" + result);
Console.ReadKey();
}
}
答案 0 :(得分:3)
Expense2
更容易阅读和理解正在发生的事情,因为从调用中可以看出哪些参数被使用。
Expense1
可能会产生各种副作用,因为调用者在调用Calculate()
之前可能会忘记设置用于计算的变量。
如果您需要访问稍后用于计算结果的值,则可以使用类似
的内容public class Expense {
public decimal ExpenseValue { get; private set; }
public int NumberOfItems { get; private set; }
public decimal Result { get; private set; }
public decimal Calculate(decimal expenseValue, int numberOfItems) {
ExpenseValue = expenseValue;
NumberOfItems = numberOfItems;
Result = ExpenseValue * NumberOfItems;
return Result;
}
public Expense() {
Calculate(0, 0);
}
}
这将允许Expense
的内部状态在对象的生命周期内保持一致,并定义其如何Calculated
答案 1 :(得分:3)
Expense2.Calculate
是确定性的(每次用相同的参数调用时都有相同的结果)并且因为它没有副作用(参数是通过属性提供的,而不是通过属性)它也是线程安全的。最后,它更简单,更容易阅读。
Expense1
是具有非线程安全状态的经典OOP训练 - 并且不保证Result
将返回线程调用Calculate
的结果。此外,阅读和维护很冗长,也很复杂。
我每次都赞成Expense2
超过Expense1
。我唯一要做的就是让它变得静态,因为必须创建一个Expense2
的实例才能调用Calculate
。
答案 2 :(得分:1)
我不喜欢Expense1一点。我认为通常应该避免使用public get / set的属性,因为它不提供封装。它甚至不比公共场地更好(虽然它确实为后面的防守条款提供了一些空间)。
然而,更糟糕的是,Calculate()方法是imo。它不需要参数,但它仍然会改变对象的内部状态。目前尚不清楚如何。同时,它写入的字段result
不会被属性Result
返回,该属性再次执行相同的计算(如果必须进行计算,通常更喜欢方法在一处房产上。)
最后,没有必要在构造函数中将基元类型初始化为其默认值,数字类型始终初始化为0.
===
Expense2更好,更清楚发生了什么。 Method采用两个名称齐全的参数,并立即给出合理的结果。
如果这个方法是该类的唯一用例,我会考虑重命名它,因为它不代表费用,它代表了一个接近费用计算器的东西。
答案 3 :(得分:1)
这一切都取决于你想做什么,但经验法则是当它们真正链接到对象时使用属性,并在它们位于对象外部时将需要的用途传递给参数。
一个简单的例子,考虑将Person作为一个类,其中一个属性是生日,所以在这种情况下你应该这样做
public class Person{
public DateTime Birthday{get;set;}
public int GetAge(){
//some implementation
}
}
另一个例子,想想有一个Cube对象,并且在这个Cube对象中你有一个方法与另一个立方体相交,在这种情况下你应该将第二个立方体作为参数传递而不是使它成为Cube的属性,因为它是某个东西外部
public class Cube{
public Cube Intersect(Cube other){
//Do your logic here
}
}