Jax*_*ler 39 java inheritance subclass superclass
我想重构一些目前由超类和两个子类组成的代码.
这些是我的课程:
public class Animal {
int a;
int b;
int c;
}
public class Dog extends Animal {
int d;
int e;
}
public class Cat extends Animal {
int f;
int g;
}
Run Code Online (Sandbox Code Playgroud)
这是我目前的代码:
ArrayList<Animal> listAnimal = new ArrayList<>();
if (condition) {
Dog dog = new Dog();
dog.setA(..);
dog.setB(..);
dog.setC(..);
dog.setD(..);
dog.setE(..);
listAnimal.add(dog);
} else {
Cat cat = new Cat();
cat.setA(..);
cat.setB(..);
cat.setC(..);
cat.setF(..);
cat.setG(..);
listAnimal.add(cat);
}
Run Code Online (Sandbox Code Playgroud)
如何重构有关公共属性的代码?
我想要这样的东西:
Animal animal = new Animal();
animal.setA(..);
animal.setB(..);
animal.setC(..);
if (condition) {
Dog anim = (Dog) animal; //I know it doesn't work
anim.setD(..);
anim.setE(..);
} else {
Cat anim = (Cat) animal; //I know it doesn't work
anim.setF(..);
anim.setG(..);
}
listAnimal.add(anim);
Run Code Online (Sandbox Code Playgroud)
sla*_*dan 37
你有一个变量类型的想法Animal
是好的.但是你还必须确保使用正确的构造函数:
Animal animal; // define a variable for whatever animal we will create
if (condition) {
Dog dog = new Dog(); // create a new Dog using the Dog constructor
dog.setD(..);
dog.setE(..);
animal = dog; // let both variables, animal and dog point to the new dog
} else {
Cat cat = new Cat();
cat.setF(..);
cat.setG(..);
animal = cat;
}
animal.setA(..); // modify either cat or dog using the animal methods
animal.setB(..);
animal.setC(..);
listAnimal.add(animal);
Run Code Online (Sandbox Code Playgroud)
提示:如果动物总是猫或狗考虑制作动物abstract
.然后编译器会在您尝试时自动发出警告new Animal()
.
And*_*lko 15
构建猫或狗的过程很复杂,因为涉及很多领域.对于构建器模式来说,这是一个很好的例子.
我的想法是为每种类型编写一个构建器并组织它们之间的关系.它可以是组合或继承.
AnimalBuilder
构建一个通用Animal
对象和管理a
,b
,c
领域CatBuilder
需要一个AnimalBuilder
(或延伸它),并继续建立一个Cat
对象管理f
,g
字段DogBuilder
需要一个AnimalBuilder
(或延伸它),并继续建立一个Dog
对象管理d
,e
字段如果您不想创建构建器,请考虑为每个子类引入一个具有有意义名称的静态工厂方法:
Animal animal = condition ? Dog.withDE(4, 5) : Cat.withFG(6, 7);
// populate animal's a, b, c
listAnimal.add(animal);
Run Code Online (Sandbox Code Playgroud)
它将简化构造并使其更简洁,更易读.
Tal*_*dar 11
回答
一种方法是在类中添加适当的构造函数.往下看:
public class Animal {
int a, b, c;
public Animal(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
public class Dog extends Animal {
int d, e;
public Dog(int a, int b, int c, int d, int e) {
super(a, b, c);
this.d = d;
this.e = e;
}
}
public class Cat extends Animal {
int f, g;
public Cat(int a, int b, int c, int f, int g) {
super(a, b, c);
this.f = f;
this.g = g;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,要实例化对象,您可以执行以下操作:
ArrayList<Animal> listAnimal = new ArrayList();
//sample values
int a = 10;
int b = 5;
int c = 20;
if(condition) {
listAnimal.add(new Dog(a, b, c, 9, 11));
//created and added a dog with e = 9 and f = 11
}
else {
listAnimal.add(new Cat(a, b, c, 2, 6));
//created and added a cat with f = 2 and g = 6
}
Run Code Online (Sandbox Code Playgroud)
这是我在这种情况下使用的方法.它通过避免大量的"设置"方法使代码更清晰,更可读.注意,这super()
是对超类'(Animal
在本例中)构造函数的调用.
奖金
如果您不打算创建该类的实例Animal
,则应将其声明为abstract
.抽象类不能实例化,但可以是子类,可以包含抽象方法.声明这些方法没有正文,这意味着所有子类都必须提供它们自己的实现.这是一个例子:
public abstract class Animal {
//...
//all animals must eat, but each animal has its own eating behaviour
public abstract void eat();
}
public class Dog {
//...
@Override
public void eat() {
//describe the eating behaviour for dogs
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以召集eat()
任何动物!在前面的示例中,使用动物列表,您可以执行以下操作:
for(Animal animal: listAnimal) {
animal.eat();
}
Run Code Online (Sandbox Code Playgroud)