我最近在C#中将SOLID做到了非常极端的水平,并且在某些时候意识到我现在基本上没有做太多的事情.在我最近再次开始研究F#之后,我认为对于我现在正在做的很多事情,它可能是更合适的语言选择,所以我想尝试将一个真实的C#项目移植到F#作为概念的证明.我想我可以推出实际的代码(以一种非惯用的方式),但我无法想象一个架构会是什么样的,它允许我以与C#类似的灵活方式工作.
我的意思是我有很多小类和接口,我使用IoC容器编写,我也使用了像Decorator和Composite这样的模式.这导致(在我看来)非常灵活和可演化的整体架构,使我能够在应用程序的任何位置轻松替换或扩展功能.根据所需更改的大小,我可能只需要编写一个新的接口实现,在IoC注册中替换它并完成.即使更改更大,我也可以替换部分对象图,而应用程序的其余部分只是像以前一样.
现在使用F#,我没有类和接口(我知道我可以,但我认为这与我想要进行实际函数式编程的时间不同),我没有构造函数注入,而且我没有IoC容器.我知道我可以使用更高阶函数做类似Decorator模式的东西,但这似乎并没有给我带有构造函数注入的类的灵活性和可维护性.
考虑这些C#类型:
public class Dings
{
public string Lol { get; set; }
public string Rofl { get; set; }
}
public interface IGetStuff
{
IEnumerable<Dings> For(Guid id);
}
public class AsdFilteringGetStuff : IGetStuff
{
private readonly IGetStuff _innerGetStuff;
public AsdFilteringGetStuff(IGetStuff innerGetStuff)
{
this._innerGetStuff = innerGetStuff;
}
public IEnumerable<Dings> For(Guid id)
{
return this._innerGetStuff.For(id).Where(d => d.Lol == "asd");
}
}
public class GeneratingGetStuff : IGetStuff
{
public IEnumerable<Dings> For(Guid id)
{
IEnumerable<Dings> dingse;
// somehow knows how to …Run Code Online (Sandbox Code Playgroud) 我听到(并在这个网站上阅读)很多关于"赞成合成而非继承".
但是什么是Compositon?我从Person:Mammal:Animal的角度理解继承,但我无法在任何地方看到Compostion的定义.有人可以填写我吗?
我知道之前已经讨论过这个问题,但似乎总是假设继承至少有时候比组合更好.我想挑战这个假设,希望获得一些理解.
我的问题是:既然你可以完成与对象组合东西,你可以用经典的继承和自经典的继承是很经常被滥用[1] ,自对象组合为您提供了灵活地改变委托对象运行时,为什么你会永远使用经典继承?
我可以理解为什么你会推荐Java和C++等语言中的继承,这些语言不能提供方便的委派语法.在这些语言中,只要不明显不正确,就可以使用继承来节省大量的输入.但是像Objective C和Ruby这样的其他语言提供了经典的继承和非常方便的委托语法.Go编程语言是我所知道的唯一一种语言,它认为经典继承比它的价值更麻烦,并且仅支持代码重用的委托.
陈述我的问题的另一种方式是:即使您知道经典继承对于实现某个模型不是不正确的,那么这个理由是否足以使用它而不是组合?
[1]许多人使用经典继承来实现多态,而不是让他们的类实现接口.继承的目的是代码重用,而不是多态.此外,有些人使用继承来模拟他们对"is-a"关系的直观理解,这种关系往往是有问题的.
更新
我只想在谈到继承时澄清我的意思:
我在谈论一种继承的类型,即一个类继承自部分或完全实现的基类.我不是在谈论继承纯粹抽象的基类,这与实现接口相同,我记录的并不反对.
更新2
我知道继承是实现C++多态性的唯一方法.在这种情况下,显而易见的是你必须使用它.所以我的问题仅限于Java或Ruby等语言,这些语言提供了实现多态的不同方法(分别是接口和鸭子类型).
我面临着一个持续的问题,即彼此区分授权,组合和聚合,并确定最好使用一个而不是另一个的情况.
我已经查阅了Java OO分析和设计书籍,但我的困惑仍然存在.主要解释是:
委派:当我的对象使用另一个对象的功能而不改变它.
组成:我的对象由其他对象组成,而这些对象在我的对象被销毁之后又不能存在 - 垃圾收集.
聚合:我的对象包含其他对象,即使在我的对象被销毁之后也可以存活.
是否有可能有一些简单的例子来说明每个案例,以及它们背后的原因?除了我的对象只是引用另一个对象之外,还能展示这些示例吗?
关于组合与继承在线有很多信息,但我还没有找到适合JavaScript的例子.使用以下代码演示继承:
function Stock( /* object with stock names and prices */ ) {
for (var company_name in arguments[0]) {
// copy the passed object into the new object created by the constructor
this[company_name] = arguments[0][company_name];
}
}
// example methods in prototype, their implementation is probably redundant for
// this question, but list() returns an array with toString() invoked; total()
// adds up the stock prices and returns them. Using ES5 feature to make
// inherited properties non-enumerable
Stock.prototype = …Run Code Online (Sandbox Code Playgroud) 我知道如果你没有自己实现,编译器有时会提供一个默认的复制构造函数.我很困惑这个构造函数到底是做什么的.如果我有一个包含其他对象的类,其中没有一个具有声明的复制构造函数,那么行为是什么?例如,像这样的类:
class Foo {
Bar bar;
};
class Bar {
int i;
Baz baz;
};
class Baz {
int j;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我这样做:
Foo f1;
Foo f2(f1);
Run Code Online (Sandbox Code Playgroud)
默认的复制构造函数会做什么?将编译器生成的复制构造函数Foo调用编译器生成的构造函数Bar进行复制bar,然后调用编译器生成的复制构造函数Baz吗?
我正在回顾我在面向对象编程方面的知识.在类主题之间的关系下,我遇到了一些对我来说有点模棱两可的关系.
我知道依赖"使用-a"和继承"是-a"但我对聚合,组合,关联和直接关联有点不熟悉; 还有,他们中的哪一个是"有一种"关系.有些人使用Aggregation与Association互换.
什么是直接协会?还有什么是作文?在UML图中,表示它们的箭头是不同的.如果你能为我清除这些事情,我将非常感激.
在Scala中,我已经看到了这些结构
trait T extends S
Run Code Online (Sandbox Code Playgroud)
和
trait T { this: S =>
Run Code Online (Sandbox Code Playgroud)
用于实现类似的东西(即S必须在创建实例之前定义抽象方法).他们之间有什么区别?你为什么要用另一个呢?
我想问一个关于如何处理简单的面向对象设计问题的问题.我对自己处理这种情况的最佳方法有一些想法,但我有兴趣听听Stack Overflow社区的一些意见.还赞赏相关在线文章的链接.我正在使用C#,但问题不是语言特定的.
假设我写一个视频商店应用程序,其数据库中有一个Person表,其中PersonId,Name,DateOfBirth和Address领域.它还有一个Staff表,其中包含指向a的链接PersonId,以及一个Customer也链接到的表PersonId.
一个简单的面向对象的方法是说Customer"是一个" Person,因此创建类有点像这样:
class Person {
public int PersonId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Address { get; set; }
}
class Customer : Person {
public int CustomerId { get; set; }
public DateTime JoinedDate { get; set; }
}
class Staff …Run Code Online (Sandbox Code Playgroud) 好吧,所以我不是Haskell程序员,但我对Haskell背后的许多想法非常感兴趣,并且我正在研究它.但是我被困在第一个方面:我似乎无法绕过Monads,这似乎是相当基础的.我知道有一百万个关于SO的问题要求解释Monads,所以我会更加具体地说明了什么在困扰我:
我读了这篇优秀的文章(Javascript中的介绍),并认为我完全了解Monads.然后我读了Monads上的维基百科条目,看到了:
多态类型(M t)→(t→M u)→(M u)的绑定操作,其中Haskell由中缀运算符表示>> =.它的第一个参数是monadic类型的值,它的第二个参数是一个函数,它从第一个参数的基础类型映射到另一个monadic类型,其结果是在其他monadic类型中.
好的,在我引用的文章中,bind是一个仅占用一个参数的函数.维基百科说两个.我认为我对Monads的理解如下:
但是肯定有一些错误,因为我的bind概念需要一个参数:一个函数.但是(根据维基百科)Haskell的绑定实际上有两个参数!我的错误在哪里?
composition ×10
oop ×6
inheritance ×3
aggregation ×2
java ×2
c++ ×1
contains ×1
currying ×1
delegation ×1
f# ×1
haskell ×1
javascript ×1
monads ×1
scala ×1
self-type ×1
traits ×1
uml ×1