假设我有一个基类
Fruit
public class Fruit {
String name;
public Fruit(String name) {
this.name = name
}
}
我有类
Apple()
,它扩展了 Fruit()
,并且我给了该类两个构造函数。
public class Apple extends Fruit {
// constructor one
public Apple() {
this("Apple");
}
// constructor two
public Apple(String name) {
super(name);
}
}
这让我可以拨打
new Apple()
以及 new Apple("Red Apple")
与其必须将
constructor one
添加到 Fruit
的每个派生类,我更希望 Fruit
类似于以下内容:
public class Fruit {
String name;
// Automatically assign the classname from the derived class
public Fruit() {
this(this.getClass().getSimpleName());
}
public Fruit(String name) {
this.name = name
}
}
然后我可以从
constructor one
中删除 Apple
,因为它将继承自 Fruit
理想情况下,这会让我拨打
new Apple()
并自动将 Apple.name
设置为 Apple
不幸的是,
this(this.getClass().getSimpleName());
抛出了错误
java cannot refer to 'this' nor 'super' while explicitly invoking a constructor
我在其他语言中使用类似的模式,没有任何问题。 如何将派生类名称分配为基类构造函数中的参数? 在 Java 中这样的事情可能吗?
您始终可以按照您喜欢的方式实现该方法
getName()
。 (并确保在您的代码中没有人直接访问成员变量name
)。但无论如何,如果您希望构造函数 new Apple()
与 new Apple(String name)
一起可用,那么您需要实现两者,以及 Fruit()
和 Fruit(String)
。
但是,当然,还有其他更简单的方法:
public class Constructoriz0r {
public static void main(final String... args) {
{
final Apple a = new Apple();
System.out.println("a1 name: " + a.getName());
}
{
final Apple a = new Apple().setName("iThink");
System.out.println("a2 name: " + a.getName());
}
{
final Banana b = new Banana();
System.out.println("b1 name: " + b.getName());
}
{
final Banana b = new Banana().setName("YouDo");
System.out.println("b2 name: " + b.getName());
}
}
static public class Fruit<T> {
private String mName = null;
public T setName(final String pName) {
mName = pName;
@SuppressWarnings("unchecked") final T ret = (T) this;
return ret;
}
public String getName() {
if (mName == null) mName = getClass().getSimpleName();
return mName;
}
}
static public class Apple extends Fruit<Apple> { /* apple stuff */ }
static public class Banana extends Fruit<Banana> { /* banana stuff */ }
}
然后我可以从 Apple 中删除构造函数一,因为它将继承自 Fruit
不,你不会。 java不是这样工作的。简单的例子:
class Parent {
private final String name;
public Parent() {
this("Jane");
}
public Parent(String name) {
this.name = name;
}
}
class Example extends Parent {
public Example(String name) {
super(name);
}
static void test() {
new Example(); // compiler error
}
}
在java中,构造函数不继承。方法继承 - 如果您
class Y extends X
其中 X 包含某个方法,那么 Y 也自动包含该方法(事实上,您不能“删除它”,最多只能覆盖它)。但构造函数根本不这样做。您可以使用 super
语法来调用它们。到这里就结束了。
但是,这可能会令人困惑!有 2 个不相关的 Java 语言特性使其看起来像是构造函数继承,但实际上并非如此:
如果你的类根本没有构造函数,那么java会假设你打算写public YourClassName() {}
- 就像这样,java将表现得好像你有一个公共的无参数不做任何事的构造函数。
需要来调用this
或
super
,他们不能不调用。如果你没有这样做,编译器会假设你打算用
super()
来启动你的构造函数。此规则也适用于上一个项目符号。
class Example {
Example() {
System.out.println("In example constructor");
}
}
class Child extends Example {
}
class Main {
public static void main(String[] args) {
new Child(); // prints 'In example constructor'
}
}
但是,请不要误会,这与 Child “继承”构造函数无关。事实并非如此。没有定义构造函数,所以 java 玩了一个相信的游戏,就像你写的那样 public Child() { super(); }
。因此,你的问题现在几乎完全被排除了。
但是,为了争论:
你根本做不到。不是java的工作原理。然而,解决方案通常是与哨兵合作。字段应该是
private
,而不是包私有或受保护。这使我们能够完全控制它。如果您希望其他人访问该“字段”,请创建一个吸气剂。因为你可以控制它。现在它是私有的,我们可以规定,如果字符串是某个值,则
意味着只继承该名称。因此:
public class Fruit {
private final String name;
public Fruit() {
this.name = null;
}
public Fruit(String name) {
if (name == null) throw new NullPointerException("name");
this.name = name;
}
public String getName() {
return this.name != null ? name : this.getClass().getName();
}
}
在这里,只要名称相关,我们就检查该字段:如果它为空,我们返回类名。否则我们返回该字段。