标签: composition

Liskov替代和组成

假设我有这样一个类:

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)

.net c# liskov-substitution-principle composition

9
推荐指数
2
解决办法
1416
查看次数

如何用Java编写可靠的Pure Aggregation(组合)游戏对象?

所以我刚开始用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)

java interface composition game-engine

9
推荐指数
1
解决办法
2958
查看次数

扩展JFrame

扩展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)

java inheritance swing composition jframe

9
推荐指数
2
解决办法
7991
查看次数

我们什么时候使用ruby模块和使用类组合?

之前已经提出过与此类似的问题,但我特别要求使用组合作为使用模块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,还是想要使用合成?

ruby inheritance multiple-inheritance composition mixins

9
推荐指数
1
解决办法
4600
查看次数

如何在MEF中处理具有相同依赖项的不同版本的模块?

目前,我已经配置了一个模块文件夹,并且所有模块程序集及其依赖项都存在于那里.我担心,在半年的时间里,有人建立一个新的模块,和它的依赖覆盖旧版本的依赖.

如果我想自己开发某种模块的注册表,如果开发者注册了一个新的模块,并赋予它的模块文件夹的子文件夹的名字?DirectoryCatalog如果我必须告诉主机模块,这种方式会减少使用a的便利性.

.net c# wpf mef composition

9
推荐指数
1
解决办法
992
查看次数

使用Play的ActionBuilder时如何包装动作(以任何顺序)?

我正在使用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

9
推荐指数
1
解决办法
4993
查看次数

这是一个有效的类型,我如何满足它?(组成两个二元函数)

我的问题很简单,因为任何人开始使用haskell我一直在考虑类型,功能组成以及如何应用它们.我开始考虑((+) . (*))可能的结果.

现在很明显,这个问题的解决方案是开放ghci并找出答案.所以我这样做并检查了类型:

?> :t ((*) . (+))
((*) . (+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)

这种类型可能吗?我很难理解它可能是什么或它意味着什么?

再次为这个简单化的问题道歉,我试图加入到函数中的一切都失败了.我只是试图通过二元函数来开发函数组合的直觉.

haskell composition

9
推荐指数
2
解决办法
154
查看次数

继承,组合和默认方法

通常承认,通过继承扩展接口的实现不是最佳实践,并且该组合(例如,从头开始再次实现接口)更加可维护.

这是有效的,因为接口契约迫使用户实现所有所需的功能.但是在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的特定结构进行了优化.

这迫使开发者

  1. 请注意,ArrayList有自己的,更有效的spliterator()实现,并手动覆盖他自己的List实现的spliterator()方法或
  2. 使用默认方法会失去大量性能.

所以问题是:在这种情况下,人们应该更喜欢构成而不是继承吗?

java inheritance composition java-8 default-method

9
推荐指数
1
解决办法
607
查看次数

在Haskell中复制Numpy的高级索引/切片

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)

polymorphism recursion haskell numpy composition

9
推荐指数
1
解决办法
201
查看次数

直觉与设计原则

我有这样的类层次结构Beverage -> Coffee-> Latte.哪里Beverageabstract超被延长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)

java inheritance design-patterns composition

9
推荐指数
1
解决办法
209
查看次数