代码之家  ›  专栏  ›  技术社区  ›  Philippe Beaudoin

在Java中,哪种方法更可取:将字段存储两次,还是将其作为受保护的对象存储在基类中?

  •  2
  • Philippe Beaudoin  · 技术社区  · 15 年前

    我很少使用继承,但当我使用继承时,有时会遇到以下问题。鉴于:

    • Logger .
    • 给定父类和子类都需要使用此字段。

    我从两个不同的角度看这个问题:

    class ChildClass extends ParentClass {
      private Logger logger;
      public ChildClass(Logger logger) {
        super(logger);
        this.logger = logger;
      }
    }
    
    class ParentClass {
      private Logger logger;
      public ParentClass(Logger logger) {
        this.logger = logger;
      }
    }
    

    或:

    class ChildClass extends ParentClasss {
      public ChildClass(Logger logger) {
        super(logger);
      }
    }
    
    class ParentClass {
      protected Logger logger;
      public ParentClass(Logger logger) {
        this.logger = logger;
      }
    }
    

    ParentClass 但我从来没有遇到过。

    就我个人而言,我更喜欢第二种方法,其基本原理是较小的数据大小胜过封装,但我经常遇到野生的第一个版本。有没有更好的方法来做这件事?

    4 回复  |  直到 15 年前
        1
  •  3
  •   davmac    15 年前

    我不认为有一个绝对可取的方法,但是一般来说,如果您知道子类可能需要记录器-就像您在本例中所做的那样-那么您应该通过使字段受保护或添加受保护的getter来访问它。有些人会说,添加getter更好。

    “在野外”看到重复字段的一个原因是,子类是第二次写入的,并且修改父类并不总是可能的。

        2
  •  2
  •   Stephen C    15 年前

    然而:

    • 我宣布它为 private 在父类中,并提供 protected final 吸气剂法。
    • 如果你真的声明 protected 父类的属性,也应该使其 final .
    • Log4j

        this.logger = Logger.getLogger(this.getClass());
      

    这些都是相对较小的问题,但是(IIRC)默认PMD规则集包含一个关于 受保护的

    ... 但我经常在野外遇到第一个版本。

    是的,很多代码在野外是不完美的,正如我所说,这些是相对较小的问题。

    后续行动

    不,我不认为编译器会这么做:

    • 在大多数情况下,这样一个优化的回报是很小的,而JIT编译器计算出优化是有效的CPU成本将是巨大的。

    不过,我使用Guice已经有一段时间了,注入logger而不是依赖静态工厂看起来是一种标准做法。

    我认为这是一个特定于Guice的习语/实践。在我的经验中,普通的Java应用程序/库很少将logger作为参数传递。

        3
  •  0
  •   akf    15 年前

    private ,甚至作为 protected 字段对其包的成员(以及任何子类)可见。但是,如果是 Logger . 继承可能更容易理解/维护实现。

        4
  •  0
  •   John    15 年前

    我也会使用第二种方法。

    储存 logger 两次。在Java中,所有 变量是 指针 ParentClass ChildClass 都指向同一个 实例。

    第二种方法是继承的优点之一的典型例子,即共享功能和属性。