草庐IT

java - 我怎样才能避免在子类中创建无用的传递构造函数只是为了将参数传递给 "super()"?

coder 2024-03-07 原文

在 Java 中,据我所知,子类不会继承具有参数的构造函数。

例如

public class Parent {
    public Parent(int x) {
        DoSomethingWithX(x);
    }
}

public class Child extends Parent {
    // Compile fails with "Implicit super constructor Parent() is undefined 
    // for default constructor. Must define an explicit constructor
}

修复它的唯一方法是在 Child 类中创建一个无用的传递构造函数:

public class Child extends Parent {
    public Child(int x) {
         super(x);
    }
}

问题:

如果我有一个复杂的子类层次结构,有 6-10 个子类,添加这样一个带有参数的无意义传递构造函数到每个子类似乎是个坏主意!

  • 简单的代码看起来很愚蠢(10 个类中相同方法的 10 个副本)
  • 更糟糕的是,与任何代码重复一样,代码变得脆弱 - 需要在 10 个地方而不是一个地方进行任何更改(例如,再添加 1 个参数)。

问题:

对于大型类层次结构,有没有办法避免这个问题?

注意事项:

我知道一个参数的解决方案(有一个 setter,必须与构造函数分开调用)。但是这个解决方案有几个很大的缺点,因此不被接受。

最佳答案

大约 15 年前,我遇到了一个与您的问题类似的问题,它具有非常广泛(但只是稍微深一点)的层次结构(是的,伙计们,这是有原因的) .但是,由于它们都派生 self 们定期需要向其添加更多信息的基类,因此很快就会发现,向基类构造函数添加参数非常痛苦。

默认情况下不继承构造函数是件好事,但有时您希望继承它们。有时我想要一个可以添加到类中的编译时注释,以告诉编译器“为我没有明确实现的任何 super 构造函数自动生成构造函数”。但我们没有它,如果 JSR 完全成功,则需要数年时间才能完成......

没有那个神奇的注释,我们使用的解决方案正是@psabbate mentioned in his/her comment :

what if your constructors receive a Map, or a CustomClass class that contains every parameter you could possible need. That way if you need to change parameters and arguments you can only change the class you are interested about.

...但是参数类具有特定的类型层次结构(不是 Map)。

为了完整起见,举个例子:

// The standard parameters needed
class StandardParams {
    private String thisArg;

    public StandardParams(String thisArg) {
        this.thisArg = thisArg;
    }

    public String getThisArg() {
        return this.thisArg;
    }
}

// The base class
class Base {
    public Base(StandardParams args) {
        System.out.println("Base: " + args.getThisArg());
    }
}

// A standard subclass
class Sub1 extends Base {
    public Sub1(StandardParams args) {
        super(args);
        System.out.println("Sub1 thisArg: " + args.getThisArg());
    }
}

对我来说,这甚至不是“最不糟糕的”。具有表示层次结构所需的基本信息的类型是富有表现力的。

如果一个子类需要比标准参数更多的信息(这是为我们准备的),您可以选择第二个参数类类型作为第二个参数(但是树中有两种类型的构造函数) 或在参数类层次结构中使用继承;我们使用了后者:

// Extended parameters (naturally you make these names meaningful)
class ExtendedParams extends StandardParams {
    private String thatArg;

    public ExtendedParams(String thisArg, String thatArg) {
        super(thisArg);
        this.thatArg = thatArg;
    }

    public String getThatArg() {
        return this.thatArg;
    }
}

// A subclass requiring extended parameter information
class Sub2 extends Base {
    public Sub2(ExtendedParams args) {
        super(args);
        System.out.println("Sub2 thisArg: " + args.getThisArg());
        System.out.println("Sub2 thatArg: " + args.getThatArg());
    }
}

在我的案例 IIRC 中,我们只有三个参数类(树中特定分支的标准一个和两个子类)跨越层次结构中大约 30 个主要类。

最后一点:对我们来说,在构建参数类时,我们需要向参数类提供一组核心内容,这些内容没有变化,并且有大约八个选项具有合理的基本默认值,但您可以覆盖.为了避免参数类中构造函数的爆炸式增长,我们最终对它们做了一些穷人的构建器模式(“穷人的”因为我们让这些类成为它们自己的构建器而不是将它们分开;这只是没有必要为了 对其严格,更改的内容具有廉价的默认值,因此即使在构建时实例也始终处于有效状态)。所以我们的构造看起来像这样:

Thingy t = new Thingy(
    new ThingyParams(basic, construction, info)
    .withAnswer(42)
    .withQuestion("Life, the Universe, and Everything")
);

关于java - 我怎样才能避免在子类中创建无用的传递构造函数只是为了将参数传递给 "super()"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39732984/

有关java - 我怎样才能避免在子类中创建无用的传递构造函数只是为了将参数传递给 "super()"?的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  6. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  7. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  8. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  9. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  10. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

随机推荐