gpt4 book ai didi

java - 如果要使用子类型的属性,如何防止显式转换?

转载 作者:行者123 更新时间:2023-12-01 17:44:12 27 4
gpt4 key购买 nike

因此,每当我进行显式强制转换时,编译器就会提示。我可以通过使用 @SuppressWarnings 注释来防止这种情况。此时,我的代码中会有很多此注释,这让我怀疑还有另一种我不知道的方法。

让我们看一下这个例子

class CutePet
{
public void pet()
{
System.out.println( "The cute pet gets some pets" );
}
}

class Cat extends CutePet
{
public void letOutside()
{
System.out.println( "The cat goes outside" );
}


public void letInside()
{
System.out.println( "The cat comes inside" );
}


public void removeTick()
{
System.out.println( "The cat looses all ticks" );
}
}

class Dog extends CutePet
{
public void goForAWalk()
{
System.out.println( "The Dog goes for a walk" );
}


public void tellHimWhatHeIs()
{
System.out.println( "The Dog is a good boy" );
}
}

class caretaker
{
public void takeCare( CutePet pet )
{
if( pet instanceof Cat )
{
pet.pet();
((Cat)pet).letOutside();
((Cat)pet).letInside();
((Cat)pet).removeTick();
}
else if( pet instanceof Dog )
{
pet.pet();
((Dog)pet).goForAWalk();
((Dog)pet).tellHimWhatHeIs();
}
}
}

看守人事先不知道他会得到什么样的宠物,他有几种不同种类的宠物。我尝试为 Cute pet 类提供一个返回枚举的 getType() 方法。通过这个枚举,我可以删除“instanceof”,但 Actor 阵容仍然存在。

我错过了什么吗?

最佳答案

如果这是一个现实世界的问题,看护人会根据宠物的外观识别出他养的是哪种宠物。虽然“实例”是查看它的一种方式,但您可能需要考虑根据需要直接使用子类型重载 takeCare 方法。例如:

class Caretaker {
public void takeCare(Cat pet) {
pet.pet();
pet.letOutside();
pet.letInside();
pet.removeTick();
}

public void takeCare(Dog pet) {
pet.pet();
pet.goForAWalk();
pet.tellHimWhatHeIs();
}
}

换句话说,看护人知道针对他收到的宠物类型该怎么做(已经有适当的方法)。

编辑

针对一些评论,是的,原始示例将问题进一步转移。如果您有一系列或一系列通用宠物,那么您仍然需要弄清楚必须将哪些类型的宠物交给看护人。从概念上讲,宠物应该能够抚摸自己,带自己散步等,这似乎很奇怪(这些方法是宠物类的一部分,而应该由看护者对宠物进行这些操作)。

此后,我使用下面的完整工作示例重写了代码,该示例使用具有 perform 方法的 Job 类。此方法将根据看护者拥有的动物类型返回适当的工作。然后,看护人就可以对相关宠物执行这项工作。见下文。

以这种方式做事可以避免 instanceof。虽然instanceof实际上有多好/坏是有争议的,但在可能的情况下,应该由对象本身来告诉我它需要什么,否则整个多态性概念很快就会变得非常棘手。

import java.util.Arrays;

public class Test {


public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Arrays.asList(
new Cat("Cat1"),
new Cat("Cat2"),
new Dog("Dog1")
).forEach(caretaker::takeCare);
}

interface CutePet {
String whoAmI();
Job whatINeed();
}

abstract static class NamedCutePet implements CutePet {
private final String name;

public NamedCutePet(String name) {
this.name = name;
}
public String whoAmI() {
return this.name;
}
}

static class Cat extends NamedCutePet {

public Cat(String name) {
super(name);
}

@Override
public Job whatINeed() {
return new CatJob(this);
}
}

static class Dog extends NamedCutePet {


public Dog(String name) {
super(name);
}

@Override
public Job whatINeed() {
return new DogJob(this);
}
}

static class Caretaker {

void takeCare(CutePet pet) {
pet.whatINeed().perform();
}
}

static abstract class BaseJob implements Job {

void pet(CutePet pet) {
System.out.println(String.format("The cute pet %s gets some pets", pet.whoAmI()));
}
}

static class DogJob extends BaseJob {

private final Dog dog;

public DogJob(Dog dog) {
this.dog = dog;
}

@Override
public void perform() {
pet(dog);
takeDogFarAWalk(dog);
tellHimWhatHeIs(dog);
}
private void takeDogFarAWalk(Dog dog) {
System.out.println(String.format("The dog %s goes for a walk", dog.whoAmI()));
}

private void tellHimWhatHeIs(Dog dog) {
System.out.println(String.format("The dog %s is a good boy", dog.whoAmI()));
}
}

static class CatJob extends BaseJob {

private final Cat cat;

public CatJob(Cat cat) {
this.cat = cat;
}

@Override
public void perform() {
pet(cat);
letOutside(cat);
letInside(cat);
removeTick(cat);
}

private void letOutside(Cat cat) {
System.out.println(String.format("The cat %s goes outside", cat.whoAmI()));
}

private void letInside(Cat cat) {
System.out.println(String.format("The cat %s comes inside", cat.whoAmI()));
}

private void removeTick(Cat cat) {
System.out.println(String.format("The cat %s loses all ticks", cat.whoAmI()));
}
}

interface Job {
void perform();
}

}

关于java - 如果要使用子类型的属性,如何防止显式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57483895/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com