如何编写一个可以被两个非继承类共享的方法
我有 2 个类,都具有相同的方法(名称 + 类型 + 行为)和相同的属性(名称 + 类型)
public class Country
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
public class Person
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
- 不允许 Person
和 Country
类继承
在上面的代码中,您可以看到 Person
类具有与 Country
类类似的方法(DisplayName
)。我正在寻找一种方法,以便两个类可以共享相同的方法代码,我想这样做,因为在我的真实代码中-我想共享的方法非常大,每当我更改一个类中的代码时,我都必须复制粘贴在其他班级也是如此。我觉得这不是正确的方法。
请建议如何解决这个问题。
I am having 2 classes, both having a same method(name + type +behavior) and a same property (name + type)
public class Country
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
public class Person
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
-- Person
and Country
classes are not allowed to inherit
In the above code you can see Person
class has similar method(DisplayName
) like Country
class. I am looking for a way so that both classes can share the same method codes, i want to do this because in my real codes- Method which i want to share is very big and whenever i change code in one class i have to copy paste it in other class too. That i feel is not the correct way.
Please suggest how to resolve this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
你说它们不能从公共基类继承,但你可以添加一个接口,对吗?我建议为他们每个人提供一个通用的界面。然后为该接口定义一个扩展方法 。 VS 中将出现每个方法的方法。
(假设:如果扩展方法访问的类成员是公共的或内部的,这将起作用。)
。 。 。在与扩展方法相同的类中,定义(不是作为扩展方法)函数 doSomeDisplayLogic 来执行通用逻辑。 (第一次遇到的问题:确保扩展方法位于同一个命名空间中,或者其命名空间也包含在调用代码中。)
我不知道您是否是扩展方法的新手。他们非常强大。 (就像许多强大的功能一样,它们也可能被滥用)。 接口上的扩展方法乍一看似乎很疯狂,直到您清楚地了解扩展方法的真正工作原理。如果没有这个,LINQ 将无法工作!
更新:我在上面看到您的评论,这些类不能从公共类继承,因为它们已经从公共类继承(我认为不能弄乱太多)。我想指出一个选项2,基于此:创建一个国家/人/等的新类。将继承自,它本身继承自现有的公共父类。可以这么说,现有的基类将成为祖父母类。如果 Country 和 Person 除了此 DisplayName 方法之外还有其他共同特征,那么这将成为更可行的路线。如果您只需要 DisplayName,那么接口/扩展模式可能会更好。
You say they cannot inherit from a common base class, but you could add an interface, right? I suggest giving them each a common interface. Then define an extension method for that interface. The method will appear for each of them in VS.
(Assumption: this will work if the class members accessed by the extension methods are public or internal.)
. . . And in the same class as your extension method, define (not as an extension method) a function doSomeDisplayLogic to do your common logic. (first-time gotcha: make sure the extension method is in the same Namespace or the its namespace is also included in the calling code.)
I don't know if you're new to extension methods or not. They are very powerful. (And like many powerful features, they can be abused). An extension method on an interface seems crazy at first, until you get straight in your head how extension methods really work. LINQ wouldn't work without this!
Update: I see your comment above that the classes can't inherit from a common class, because they are already inheriting from a common class (which I assume can't be messed with too much). I would like to point out an Option 2, based on this: Creating a new class that Country/Person/etc. will inherit from, that itself inherits from the existing common parent class. The existing base class would become a grandparent class, so to speak. This would become more the route to go if Country and Person have other common characteristics besides this DisplayName method. If DisplayName is all you're after, the Interface/Extension pattern might be better.
定义一个接口
然后添加一个扩展
Define an interface
then add an extension
我建议在某些情况下避免扩展方法,当您需要两个类的实现略有不同时,您可能会遇到问题,然后您必须设计一个更通用的解决方案,EM 可能会导致与多重继承相同的问题。
作为更通用的 OOD 解决方案,我建议将此行为提取到由接口抽象的单独服务类中:
然后实现它并通过构造函数注入到两个类中。
此外,您可以通过构造函数甚至属性注入
Action
或Func<>
,而不是引入接口和新类,然后通过调用注入的委托来调用此方法。I would suggest to avoid Extension Methods in some cases, you can ran into a problem when you need slightly a different implementation for both classes and then you have to design a more generic solution, EM can cause the same issues like multiple inheritance does.
As more generic OOD solution I would suggest to extract this behaviour into a separate service class abstracted by an interface:
Then implement it and inject into both classes via constructor.
Also, instead of introducing the interfaces and new classes you can inject
Action
orFunc<>
via constructor or even property and then call this method by invoking an injected in delegate.您可以创建一个静态实用方法
DisplayName()
来传递显示所需的数据,或者使用组合并移动所有属性和相应的方法,例如DisplayName()
一个单独的类 - 然后使用来自Country
和Person
的此类实例。You could create either a static utility method
DisplayName()
that you pass the data needed for display, or use composition and move all properties and corresponding methods such asDisplayName()
in a separate class - then use an instance of this class from bothCountry
andPerson
.您可以实现策略模式:
注意:注入具体策略可能会更好。
You could implement a strategy pattern:
Note: it's probably better to inject the concrete strategy.
您可以使用组合:定义一个接口、一个实现该接口的类,然后让
Person
和Country
通过调用实现类上的方法来实现该接口:You could use composition: define an interface, a class that implements it, and then have
Person
andCountry
implement the interface by calling methods on the implementation class:我认为您要求的是多类继承,这在 C# 中是不允许的。 (但可以使用 C++,但你没有这样做)。
所有其他人都已确定采用接口解决方案,这可能是最好的方法。但是,根据您的描述,无论对象类型是个人还是企业,您都有一个相同的代码块。当您引用大量代码时,您不想在可能打算使用类似的常见“事物”来完成的所有其他类中复制/粘贴相同的确切代码。
举个简单的例子,您有一个功能可以构建一个人的姓名和地址(或公司名称和地址)。您的代码需要名称和最多 3 个地址行,以及城市、州、邮政编码(或其他任何内容)。因此,此类名称/地址信息的格式对于个人和企业来说是相同的。您不想在两者之间一遍又一遍地复制这个确切的方法。然而,每个单独的类仍然有自己负责的事情。
我知道这是一个简单的上下文示例,但我认为它已经表达了要点。
仅定义接口的问题是它不允许您实际实现您所引用的代码。
从您的示例中,我会考虑做一些事情的组合。创建一个静态类,其中包含您可能希望“全局”可用的方法。允许将一个参数传递给一个类的实例,该类的实例具有所有其他人都表达的接口类型,这将保证传入的对象具有您期望的所有“部分”属性/方法,并让 IT 进行操作根据需要。像这样的东西
What I THINK you are asking for is multiple class inheritance which is not allowed in C#. (but can be with C++ which you are NOT doing).
All the others have identified doing an INTERFACE solution, and probably the best way to go. However, from your description, you have a SINGLE BLOCK of code that is identical regardless of the type of object being a person or a business. And your reference to a huge block of code, you don't want to copy/paste that same exact code among all the other classes that may be intended to use similar common "thing" to be done.
For simple example, you have a functionality that builds out a person's name and address (or business name and address). You have code that is expecting a name and up to 3 address lines, plus a city, state, zip code (or whatever else). So, the formatting of such name/address information is the same for a person vs a business. You don't want to copy this exact method over and over between the two. However, each individual class still has its own things that it is responsible for.
I know its a simple example for context, but I think gets the point across.
The problem with just defining an Interface is that it won't allow you to actually implement the CODE you are referring to.
From your sample, I would consider doing a combination of things.. Create a static class with methods on it that you might want as "globally" available. Allow a parameter to be passed into it of an instance of a class that has a type of interface all the others have expressed that will guarantee the incoming object has all the "pieces" of properties / methods you are expecting, and have IT operate on it as needed. Something like
警告:这里有很多未经测试的代码,主要是疯狂猜测,因为我不同意“无继承”的基本假设。
像这样的东西应该对你有帮助。创建一个新的静态类并将您的代码粘贴到此处。
在您的类中,重构 ShowDisplayName() 以使用“this”作为参数来调用它。
...
公共无效显示名称()
{
显示名称(此);
}
...
我想知道为什么你的类不允许从基类继承它,因为恕我直言,这是解决这个问题的最正确方法。
warning: lots of untested code here, wild guessing mostly since i disagree with the base assumption "no inheritance".
something like this should help you. create a new static class and paste your code in here.
in your classes, refactor ShowDisplayName() to call that with "this" as parameter.
...
public void DisplayName()
{
DisplayName(this);
}
...
I wonder why your classes are not allowed to inherit it from a base class, since that's imho the right-est way to solve this.
有几个选项:
Name
),并为行为添加扩展方法(或只是普通的静态方法)创建采用实例的方法和一个 lambda 表达式来访问评论成员,例如
然后你可以用(比如说)来调用它
接口解决方案是更干净的解决方案,但使用委托更灵活- 您不需要能够更改所涉及的类,并且可以应对小的变化(例如
PersonName
与FooName
与Name
)A couple of options:
Name
) and add an extension method for the behaviour (or just a normal static method)Create methods which take an instance and a lambda exppession to access the comment members, e.g.
You'd then call it with (say)
The interface solution is the cleaner one, but using a delegate is more flexible - you don't need to be able to change the classes involved, and you can cope with small variations (e.g.
PersonName
vsFooName
vsName
)您可以在单独的类中定义该大方法,然后在上述两个类中调用该方法。对于静态方法,您可以使用
classname.methodname()
语法调用该方法。对于非静态方法,您必须这样做:
You can define that big method in a separate class and then call the method in both the above classes. For a static method, you can call the method using
classname.methodname()
syntax.For a non static method, you will have to do this: