假设我有这样一个类:
public sealed class Foo
{
public void Bar
{
// Do Bar Stuff
}
}
Run Code Online (Sandbox Code Playgroud)
我想扩展它以添加超出扩展方法可以做的事情....我唯一的选择是组合:
public class SuperFoo
{
private Foo _internalFoo;
public SuperFoo()
{
_internalFoo = new Foo();
}
public void Bar()
{
_internalFoo.Bar();
}
public void Baz()
{
// Do Baz Stuff
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但它还有很多工作......但是我仍遇到一个问题:
public void AcceptsAFoo(Foo a)
Run Code Online (Sandbox Code Playgroud)
我可以在这里传递一个Foo,但不是超级Foo,因为C#不知道SuperFoo确实符合Liskov替换意义......这意味着我的扩展类通过组合使用非常有限.
因此,解决它的唯一方法是希望原始的API设计者留下一个界面:
public interface IFoo
{
public Bar();
}
public sealed class Foo : IFoo
{
// etc
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以在SuperFoo上实现IFoo(因为SuperFoo已经实现了Foo,只需要更改签名).
public class SuperFoo : IFoo
Run Code Online (Sandbox Code Playgroud)
在完美的世界中,消耗Foo的方法将消耗IFoo:
public …Run Code Online (Sandbox Code Playgroud) 所以我刚开始用Java编写游戏,我正在编写我的游戏对象.现在我已经在Evolve Your Hierarchy中读到,你应该将游戏构建为组合而不是大类层次结构.由于上一个链接中的图像显示:

但是,当实际开始实现时,我有一个关于在哪里应用接口的小问题.
假设你有一个叫做Player的类,接口是Moveable和Renderable.您是使用公共接口变量实现的:
class Player {
public Moveable moveable;
public Renderable renderable;
}
class GenericMoveable implements Moveable {
// Function implementations
}
class PlayerRenderable implements Renderable {
// Function implementations
}
Run Code Online (Sandbox Code Playgroud)
或者您尝试通过将接口直接应用于对象来执行此操作:
class Player implements Moveable, Renderable {
private GenericMoveable genericMoveable;
// Non-direct Implementation of Moveable
void someMoveFunc(double x, double y) {
genericMoveable.someMoveFunc(x, y);
}
// Direct implementation of Renderable
void someRenderableFunction() {
// Player class specific code
}
}
class GenericMoveable implements Moveable {
// …Run Code Online (Sandbox Code Playgroud) 扩展JFrame而不是创建新的JFrame有什么优缺点?
例如:
public class Test extends JFrame {
setVisible(true);
}
Run Code Online (Sandbox Code Playgroud)
要么
public class Test {
JFrame test = new JFrame():
test.setVisible(true);
}
Run Code Online (Sandbox Code Playgroud) 之前已经提出过与此类似的问题,但我特别要求使用组合作为使用模块mixins的替代方法.
class Helper
def do_somthing
end
end
Run Code Online (Sandbox Code Playgroud)
如果我需要"使用"一个类而不是继承它,我只需要编写并使用它.
class MyStuff
def initialize
helper = Helper.new
helper.do_something
end
end
Run Code Online (Sandbox Code Playgroud)
为什么我要为此创建一个模块:
module Helper
def do_something
end
end
class MyStuff
include Helper
end
Run Code Online (Sandbox Code Playgroud)
我看到的唯一区别是,Helper如果我使用模块,周围不会有很多物体.但是我没有看到任何东西,周围有更多物体,而不是更大的物体.
而且,我不知道将来是否需要将其子类化.那么我该如何判断我的库的用户是想要使用模块mixin,还是想要使用合成?
目前,我已经配置了一个模块文件夹,并且所有模块程序集及其依赖项都存在于那里.我担心,在半年的时间里,有人建立一个新的模块,和它的依赖覆盖旧版本的依赖.
如果我想自己开发某种模块的注册表,如果开发者注册了一个新的模块,并赋予它的模块文件夹的子文件夹的名字?DirectoryCatalog如果我必须告诉主机模块,这种方式会减少使用a的便利性.
我正在使用Play的ActionBuilder创建各种保护我的控制器的操作.例如,我实现IsAuthenticated了以确保只有在用户登录时才能访问某些操作:
case class AuthRequest[A](user: String, request: Request[A]) extends WrappedRequest[A](request)
private[controllers] object IsAuthenticated extends ActionBuilder[AuthRequest] {
def invokeBlock[A](req: Request[A], block: (AuthRequest[A]) => Future[SimpleResult]) = {
req.session.get("user").map { user =>
block(new AuthRequest(user, req))
} getOrElse {
Future.successful(Results.Unauthorized("401 No user\n"))
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用IsAuthenticated我可以(1)将操作限制为已登录的用户,以及(b)访问登录的用户:
def auth = IsAuthenticated { implicit authRequest =>
val user = authRequest.user
Ok(user)
}
Run Code Online (Sandbox Code Playgroud)
此外,我使用ActionBuilder HasToken来确保在请求的标头中存在令牌时调用了一个动作(并且,我可以访问令牌值):
case class TokenRequest[A](token: String, request: Request[A]) extends WrappedRequest[A](request)
private[controllers] object HasToken extends ActionBuilder[TokenRequest] {
def invokeBlock[A](request: …Run Code Online (Sandbox Code Playgroud) authentication scala composition playframework playframework-2.0
我的问题很简单,因为任何人开始使用haskell我一直在考虑类型,功能组成以及如何应用它们.我开始考虑((+) . (*))可能的结果.
现在很明显,这个问题的解决方案是开放ghci并找出答案.所以我这样做并检查了类型:
?> :t ((*) . (+))
((*) . (+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)
这种类型可能吗?我很难理解它可能是什么或它意味着什么?
再次为这个简单化的问题道歉,我试图加入到函数中的一切都失败了.我只是试图通过二元函数来开发函数组合的直觉.
通常承认,通过继承扩展接口的实现不是最佳实践,并且该组合(例如,从头开始再次实现接口)更加可维护.
这是有效的,因为接口契约迫使用户实现所有所需的功能.但是在java 8中,默认方法提供了一些可以"手动"覆盖的默认行为.请考虑以下示例:我想设计一个用户数据库,该数据库必须具有List的功能.出于效率目的,我选择通过ArrayList来支持它.
public class UserDatabase extends ArrayList<User>{}
Run Code Online (Sandbox Code Playgroud)
这通常不被认为是一种很好的做法,如果真的希望列表的全部功能并遵循通常的"遗产构成"的座右铭,我宁愿这样做:
public class UserDatabase implements List<User>{
//implementation here, using an ArrayList type field, or decorator pattern, etc.
}
Run Code Online (Sandbox Code Playgroud)
但是,如果不注意,则不需要覆盖某些方法,例如spliterator(),因为它们是List接口的默认方法.问题是,List的spliterator()方法执行得比ArrayList的spliterator()方法差得多,后者已针对ArrayList的特定结构进行了优化.
这迫使开发者
所以问题是:在这种情况下,人们应该更喜欢构成而不是继承吗?
Numpy在其阵列访问运算符中具有复杂的索引/切片/步进功能.请参阅:http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
在尝试使用Haskell时,我认为尝试复制此索引功能的子集会很有教育意义.具体来说,它是"元组选择对象"或n维投影"(https://en.wikipedia.org/wiki/Projection_%28relational_algebra%29).
基本上你可以这样做:
two_d_array[0:1:1, 0:4:2]
Run Code Online (Sandbox Code Playgroud)
这将为您提供第一行,步长为1,包含前两列2(跳过1列).
换句话说,它可以将原始的二维数组投影到一个较小的二维数组中.结果仍然是二维数组.
所以这就是我在Haskell中尝试过的.
这样的函数的类型应该是这样的:
(!!!) :: (Functor f) => f a -> [(Int, Int, Int)] -> f a
Run Code Online (Sandbox Code Playgroud)
所以你可以看到类似的东西:
three_d_tensor !!! [(s1,e1,st1), (s2,e2,st2), (s3,e3,st3)]
Run Code Online (Sandbox Code Playgroud)
其中sx,ex,stx分别为start,end,step.
该示例应将原始张量投影为较小的张量,第一维受限制s1 to e1, stepping by st1,第二维受s2 to e2, stepping by st2......等限制.
所以这就是我得到的:
slicing from to xs = take (to - from + 1) (drop from xs)
stepping n = map head . takeWhile (not . null) . iterate (drop n)
(!!!) …Run Code Online (Sandbox Code Playgroud) 我有这样的类层次结构Beverage -> Coffee-> Latte.哪里Beverage是abstract超被延长Coffee.Coffee然后类增加了一些行为,但也是abstract.Latte扩展Coffee类,是一个具体的类.我已经使用继承来添加行为.并且继承确实有缺点,如超类方法的可见性,使代码易碎,代码紧密耦合.因此,编程原则Composition应该优先考虑Inheritance.但在这种情况下inheritance感觉如此自然Latte,Coffee并且Coffee是一种类型的Beverage使用composition添加行为感觉错误,尽管它的好处.所以这里的问题是
应该直觉覆盖设计原则吗?
饮料:
public abstract class Beverage {
private final String name;
private final double price;
Beverage(String name, double price){
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public abstract void …Run Code Online (Sandbox Code Playgroud) composition ×10
inheritance ×4
java ×4
.net ×2
c# ×2
haskell ×2
game-engine ×1
interface ×1
java-8 ×1
jframe ×1
liskov-substitution-principle ×1
mef ×1
mixins ×1
numpy ×1
polymorphism ×1
recursion ×1
ruby ×1
scala ×1
swing ×1
wpf ×1