我可以将实现类的引用用于java接口中声明的方法吗

我可以将实现类的引用用于java接口中声明的方法吗,java,interface,Java,Interface,我见过一些类的设计方式,其中接口具有方法声明,该方法具有其子类类型(实现类)的参数,如下所示: 接口A定义为具有方法setData,该方法具有AAbstract类型的参数,该参数是实现接口A的具体类AImpl的子类: public interface A{ void setData(AAbstract ref); } 我们有实现类AImpl: public class AImpl implements A { private AAbstract in

我见过一些类的设计方式,其中接口具有方法声明,该方法具有其子类类型(实现类)的参数,如下所示:

接口A定义为具有方法setData,该方法具有AAbstract类型的参数,该参数是实现接口A的具体类AImpl的子类:

 public interface A{    
        void setData(AAbstract ref);
    }
我们有实现类AImpl:

 public class AImpl implements A {
    private AAbstract instance; 
        public void setData(AAbstract ref) {
            this.instance= ref;
        }
    }
还有抽象的实现,比如:

 public abstract class AAbstract extends AImpl {
       public abstract void dummy(String msg);
    }

就我个人而言,我不认为这是正确的设计,我想从设计角度了解专家的意见

这种模式的最大问题是耦合-类
AImpl
和抽象类
AAbstract
是紧密耦合和循环依赖的。继承层次结构中的每个级别都知道其他级别,因此其中一个级别的更改影响其他级别的可能性非常大。通常,您会尝试设计不依赖或不了解孩子的类。也有例外,一个类的实现数量是预先知道的,并且通常不会改变,但很少。在这种情况下,
AAbstract
AImpl
之间的循环依赖关系表明,它们也可以组合成一个类


老实说,我不知道这种模式会带来什么价值
AImpl
包含
AAbstract
的一个实例,它扩展了
AImpl
,因此也包含
AAbstract
的一个实例。。。那么它是不是一直在下降?我的猜测是,在某种程度上有一个null,没有人喜欢null。

答案就是使用更具描述性的实现名称


AImpl
AAbstract
表明您正在为单个实现创建接口。在这种情况下,YAGNI适用,不需要抽象。抽象允许控制反转,允许您指定不同类型的
A
。如果只有一个实现,那么抽象就毫无用处了。当然,这在理论上很简单,因为人们创建抽象以便于在测试中模仿

抽象允许不同的实现。如果您使用
AImpl
,您会如何命名其他实现

您可以改为使用
ADefault
,这表明它是一个默认实现(如果其他实现不适合,请使用默认实现),但这仍然是您指定的问题,只是稍微淡化了一点

问问自己:“如果我有多个实现,它们之间的区别是什么?为什么我需要多个实现?”。这将帮助您为每个实现找到更具描述性的名称,允许您命名抽象
a
,然后根据存在的原因定义不同类型的
a


举一个使用
A
的例子,我相信我可以很容易地为实现找到更好的名称。例如,
Graphics
是一种抽象,
OpenGL
DirectX
是实现。这两种实现都有不同的用途,并以它们的名称进行了描述。

AAbstract没有任何问题。您还没有说明为什么它可能是一个糟糕的设计选择。总的来说,我认为它没有什么问题。@markspace我可以看到一个问题
Animal
是一个抽象概念,但似乎不需要说
AbstractAnimal
。因此,“我们什么时候应该使用匈牙利符号?”这个问题突然出现,描述了一个一致性问题。许多专业人士确实使用了它,但许多专业人士在意识到这是一个“十亿美元的错误”之前使用了
null
。糟糕的设计选择是不一致的。它允许你这样做,这实际上鼓励了脱钩。它类似于
Graphics
类作为接口的方式。一些人建议使用
IGraphics
,但另一些人建议使用更具描述性的名称implementations@VinceEmigh这里与
Graphics
类有一个显著的区别-接口
a
取决于它的实现者
AAbstract
,它本身就是一个具体类的扩展。这不完全是教科书的合同设计。因此,您将拥有一个仅依赖于其他接口的接口。
Graphics
的接口纯粹是根据原语和其他高级抽象来描述的。接口是抽象:您将所需的行为抽象到接口中。抽象是接口(契约),但允许您提供impl之间的公共属性,从而减少干冲突。正如您所说,
AAbstract
是impl的一个扩展(它抽象了impl的细节),但是它抽象了哪些具体细节<代码>A摘要未对其进行描述。它表明只有一个抽象的实现,表明实际的接口只是为了便于模拟和强制设计。(在下一篇评论中继续举例)想象一下
DirectX
OpenGL
版本控制。它们都需要抽象不同的属性,可以定义为
抽象类DirextX
,其中
DirectX14
是实际的impl
AAbstract
没有为我们提供足够的关于impl被抽象的信息,这使得它成为一个糟糕的命名选择。这不是教科书上的博士,但想法非常相似。创建这些设计是为了帮助解决问题,如果它们是被迫的(没有实际问题需要解决),它们会产生更多的问题,例如命名。这只是基于我的经验,所以如果我错了,请纠正我。这不是好的合同设计。命名是一个问题的原因是对象设计不完美——这与我关于耦合的观点基本相同。如果我有什么事