Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:访问超类的策略模式&x27;字段和方法?_Java_Inheritance_Design Patterns_Interface_Multiple Inheritance - Fatal编程技术网

Java:访问超类的策略模式&x27;字段和方法?

Java:访问超类的策略模式&x27;字段和方法?,java,inheritance,design-patterns,interface,multiple-inheritance,Java,Inheritance,Design Patterns,Interface,Multiple Inheritance,我有一个抽象类Parent,其中包含抽象方法foo()和bar()以及其他非抽象方法和字段。我需要创建4个子类(以及更高的子类),以涵盖foo()和bar():fooA(),fooB(),barA(),barB()。这些变体需要访问Parent的其他字段和方法。 换句话说,如果Java支持多重继承,那么我会有如下内容: abstract class Parent{ abstract foo(){} abstract bar(){} //other fields and m

我有一个抽象类
Parent
,其中包含抽象方法
foo()
bar()
以及其他非抽象方法和字段。我需要创建4个子类(以及更高的子类),以涵盖
foo()
bar()
fooA()
fooB()
barA()
barB()
。这些变体需要访问
Parent
的其他字段和方法。 换句话说,如果Java支持多重继承,那么我会有如下内容:

abstract class Parent{
    abstract foo(){}
    abstract bar(){}
    //other fields and methods that will be accessed foo and bar are PROTECTED
}

abstract class FooA extends Parent{
    @Override
    foo(){ ... }
}
abstract class FooB extends Parent{
    @Override
    foo(){ ... }
}
abstract class BarA extends Parent{
    @Override
    bar(){ ... }
}
abstract class BarB extends Parent{
    @Override
    bar(){ ... }
}

class ChildAA extends FooA, BarA{   
}

class ChildAB extends FooA, BarB{
}

class ChildBA extends FooB, BarA{
}

class ChildBB extends FooB, BarB{
}
我已经找到了两种解决方案,每种都有效,但都差不多。有没有更好的方法来实现这种行为?我的解决办法如下:

1) 第一个解决方案:

abstract class Parent {
    foo(){ 
        /* behaves like fooA */
    }
    //other fields and methods that will be accessed foo and bar are PROTECTED
}

class ChildAA extends Parent{
    barA(){ ... }
}

class ChildAB extends Parent{
    barB(){ ... }
}

class ChildBA extends ChildAA{
    @Override
    foo(){ /* behaves like fooB */ }
|

class ChildBB extends ChildAB{
    @Override 
    foo(){ /* behaves like fooB */ }
}
问题是它复制了
fooB()
的代码和所有只
fooB()
需要的附加方法。当需要更多的变化时,问题会变得更严重

2) 环顾四周后,我发现了设计模式策略,该策略可用于实现行为,但很尴尬,因为变体需要访问父级的字段和方法:

abstract class Parent{
    Fooable fooable;
    Barable barable;
    foo(){ fooable.foo(); }
    bar(){ barable.bar(); }
    //other fields and methods that will be accessed foo and bar are PUBLIC
}

abstract class ImplementableParent{
    Parent p;
    ImplementableParent(Parent p) { this.p = p; }
}

interface Fooable{
    foo();
}
class FooA extends ImplementableParent implements Fooable{
    FooA(Parent p){ super(p); }
    @Override 
    foo(){ /* behaves like FooA */ }
}
class FooB extends ImplementableParent implements Fooable{
    FooB(Parent p){ super(p); }
    @Override 
    foo(){ /* behaves like FooB */ }
}

interface Barable{
    bar();
}
class BarA extends ImplementableParent implements Barable{
    BarA(Parent p) { super(p); }
    @Override 
    bar() { /* behaves like BarA */ }
}
class BarB extends ImplementableParent implements Barable{
    BarB(Parent p) { super(p); }
    @Override 
    bar() { /* behaves like BarB */ }
}

class ChildAA extends Parent{
    fooable = new FooA(this);
    barable = new BarA(this);
}

class ChildAB extends Parent{
    fooable = new FooA(this);
    barable = new BarB(this);
}

class ChildBA extends Parent{
    fooable = new FooB(this);
    barable = new BarA(this);
}

class ChildBB extends Parent{
    fooable = new FooB(this);
    barable = new BarB(this);
}
这消除了重复的变化,可以扩展以适应更多的变化。然而,现在
Parent
的字段和方法是公开的,整个过程感觉非常复杂。我还担心性能开销,因为
FooA
FooB
BarA
BarB
间接访问
父方法,尽管我没有测试它

有没有更好的方法来实现这种行为

然而,现在父类的字段和方法是公共的,并且是整体的 事情感觉很复杂

您的Barable和Fooable实现本身并不保存上下文,因此它们必须使用上下文对象(这里的子类
Parent
)中的
public
方法来查询和操作它。
但是只有
Parent
方法必须是公共的,而不是它的字段

例如,对于
Parent
FooA
实施,这将是一个公平的实施:

abstract class Parent{

    private Fooable fooable;  // internals 
    private Barable barable;  // internals

    private String sharedString;  // internals
    private Integer sharedInteger;  // internals

    // public access        
    public foo(){ fooable.foo(); }
    public bar(){ barable.bar(); }

    public String getSharedString(){
        return sharedString;
    }

    public Integer getSharedInteger(){
        return sharedInteger;
    }

    public String updateSharedData(String string, Integer integer){
        // apply some logic and controls if required
        this.string = string;
        this.integer = integer;
    }

}


class FooA extends ImplementableParent implements Fooable{
    FooA(Parent p){ 
       super(p); 
    }
    @Override 
    foo(){  
        if (p.getSharedString().equals("...)){
           // some logic
           p.updateSharedData("new value", newIntegerValue);
        }
    }
}
作为旁注,将
Parent
定义为包装的
Fooable
Barable
实例的依赖项意味着
Fooable
可以操作
Barable
并反向操作。
您的实际需求中没有说明这一点。如果要防止这种情况发生,应该为上下文定义一个特定类,该类包含两种契约(
Fooable
Barable
)和另一个用于ChildXXX子类的一般契约的类之间要共享的数据和方法。

而不是在构造函数中传递一个
父类
实例,而是传递一个
上下文
实例。

在我看来,你太依赖继承了。干净代码的一般规则是更喜欢组合而不是继承

你想要的是这样的:

interface Foo {
    void foo();
}
interface Bar {
    void bar();
}
interface FooBar extends Foo, Bar {}
有几种方法可以实现这一点

父类中的内部类和工厂方法

父类
类不需要实现这些;它可以提供这样做的内部类,以便这些类能够访问受保护的成员

class Parent {
    protected int neededByFoo;
    protected int neededByBar;

    class FooA implements Foo {
        public void foo() {
            doStuffWithNeededByFoo();
        }
    }
    class FooB implements Foo {
        public void foo() {
            doStuffWithNeededByFoo();
        }
    }
    // same for the BarA and BarB implementations
}
借助工具委托类(与您的解决方案B不同)和
Parent
中的工厂方法,您可以将它们组合到实现这两个接口的实例中

    private static class FooBarDelegate implements FooBar {
        Foo fooDelegate;
        Bar barDelegate;
        private FooBarDelegate(Foo f, Bar b) { fooDelegate = f; barDelegate = b; }
        public void foo() { fooDelegate.foo(); }
        public void bar() { barDelegate.bar(); }
    }

    public FooBar fooAbarA() {
        return new FooBarDelegate(new FooA(), new BarA());
    }
    public FooBar fooBbarA() {
        return new FooBarDelegate(new FooB(), new BarA());
    }
    public FooBar fooAbarB() {
        return new FooBarDelegate(new FooA(), new BarB());
    }
    public FooBar fooBbarA() {
        return new FooBarDelegate(new FooB(), new BarB());
    }
}

现在,内部类本质上就是将策略组装到
FooBar
实例中。根本不需要子类化
Parent

在界面中使用合并方法

您可能根本不想在
Parent
类中进行组合,但在接口中:

interface FooBar extends Foo, Bar {
    public static FooBar combine(Foo f, Bar b) {
        return new FooBar() {
            foo() { f.foo(); }
            bar() { b.bar(); }
        }
    }
}
然后你会像这样使用它

Parent p = new Parent();
FooBar fb = FooBar.combine(new p.FooA(), new p.BarA());
fb = FooBar.combine(new p.FooA(), new p.BarB());
等等

方法引用

由于
Foo
Bar
是功能接口,因此可以组合
父对象的方法,而不是使用内部类

class Parent {
    public void fooA() { // do stuff }
    public void fooB() { // do stuff }
    public void barA() { // do stuff }
    public void barB() { // do stuff }
}
然后

FooBar fb = FooBar.combine(p::fooA, p::barA);
fb = FooBar.combine(p::fooA, p::barB);
// and so on

.

您是否评估了将父级中所需字段作为参数传递给
foo
bar
的选项?为什么使用抽象类而不是接口?如果不使用像Fooable和Barable这样的接口,可以将父级定义为抽象类。然后用一些字符串参数(例如“AA”、“AB”、“BA”、“BB”)定义Child,并使用开关块相应地复用foo()和bar()的实现。这对我来说是很多新信息,-我想我可以将其纳入我的设计中,-谢谢。