Oop 这是+;构造函数定义模式是否过度冗余?
我经常遇到类似的模式:Oop 这是+;构造函数定义模式是否过度冗余?,oop,design-patterns,Oop,Design Patterns,我经常遇到类似的模式: class Person { public string firstName, lastName; public Person(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } } 这感觉太多余了(我想输入“firstName”一次,而不是三次就足够了…),但我想不出合适的替代方法
class Person {
public string firstName, lastName;
public Person(string firstName, string lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
这感觉太多余了(我想输入“firstName”一次,而不是三次就足够了…),但我想不出合适的替代方法。有什么想法吗?也许我只是不知道我应该在这里使用什么样的设计模式
编辑-我想我需要详细说明一下。我不是问如何使示例代码“更好”,而是“更短”。在其当前状态下,所有成员名称都会出现4次(声明、初始化、构造函数参数),感觉相当冗余。因此,我想知道是否有一种模式(或语义糖)可以获得(大致)相同的行为,但膨胀较少。我很抱歉一开始不清楚 编辑-Dave的C#3.0初始化示例非常好,但我仍然希望得到更一般的答案。:)
编辑-我现在意识到某些语言允许更少的冗长实现;Java和C#可能不会。这取决于您试图实现的目标,以及这些特定值是否具有 在创建对象时出于某种原因进行设置 如果您只希望在构造时设置保留的值,则必须按所做的方式声明类:
class Person
{
public string FirstName { get; private set; }
public string Surname { get; private set; }
public Person(string firstName, string surname)
{
// properties are read-only so must be set as part of the constructor
this.FirstName = firstName;
this.Surname = surname;
}
}
如果需要在构造时设置属性,那么还必须像之前一样定义类。但是,您也可以在以后更改这些值
class Person
{
public string FirstName { get; set; }
public string Surname { get; set; }
public Person(string firstName, string surname)
{
this.FirstName = firstName;
this.Surname = surname;
}
}
如果属性可以在任何时候设置,也就是说,它们是否在创建时设置是可选的,那么您不需要将它们作为构造函数的一部分传入
class Person
{
public string FirstName { get; set; }
public string Surname { get; set; }
public Person()
{
}
}
在C#(3及以上)中,您仍然可以在创建过程中设置这些属性,但我不确定其他语言有哪些功能可以反映这一点:
var myPerson = new Person
{
FirstName = "Test",
Surname = "Test2",
};
示例都是C语言的,但总体上应该是真正的OOP
我不是问如何使示例代码“更好”,而是“更短”。在其当前状态下,所有成员名称都会出现4次(声明、初始化、构造函数参数),感觉相当冗余。因此,我想知道是否有一种模式(或语义糖)可以获得(大致)相同的行为,但膨胀较少
据我所知,这里并没有一个真正的设计模式,但这种重复的程度随着语言的不同而有很大的不同
例如,在Scala中,您可以将其定义为case类,并丢失所有重复:
case class Person(firstName: String, lastName: String)
类似地,在Ruby中,您可以使用属性访问器使类定义非常简短:
class Person
attr_accessor :first_name, :last_name
end
这两种方法都不完全等同于您所描述的方法,具体取决于它们是定义可变对象还是初始化。但是这种冗余显然是语言依赖的。一般模式可能是“使用一种好的编程语言”。例如,这一行Scala大致相当于您上面所写的内容:
class Person(var firstName: String, var lastName: String)
您可以在生成的Person.class
文件上运行Java反编译器,查看您必须用Java编写什么才能获得相同的功能:
public class Person {
private String firstName, lastName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String paramString) {
this.firstName = paramString;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String paramString) {
this.lastName = paramString;
}
public Person(String firstName, String lastName) {
setFirstName(firstName);
setLastName(lastName);
}
}
方法名称将略有不同(Scala使用的不是getFirstName
和setFirstName
而是firstName
和firstName
,后者反过来被编码为firstName.$eq
,因为这在Java中是非法的),但意图是相同的
如果您可以使类成为一个case类
,您还将自动生成equals
和hashCode
的正确实现
在Ruby中,您可以编写:
Person = Struct.new(:first_name, :last:name)
然后再次得到与Java示例中得到的内容非常相似的内容Struct.new
将实际合成一个大致如下所示的适当类:
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
self.first_name, self.last_name = first_name, last_name
end
end
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
有些语言被设计成冗长的,它们通常不允许您修复它 就类型声明而言,Java迫使您不仅要声明,还要重复显而易见的操作。如果您愿意使用Scala之类的语言,类型推断基本上可以解决这个问题 在Javascript中,您既没有静态类型也没有类,构造函数只是生成对象的函数,它如下所示:
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
self.first_name, self.last_name = first_name, last_name
end
end
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
名字和姓氏是公共的吗?这段代码是谁写的:)?就问题而言,这并不重要。我故意让它尽可能简单。+1,对于这句话“但是你也可以让它在以后更改这些值。”