gpt4 book ai didi

java - 如何在每个子枚举中实现具有不同第一个参数的功能接口(interface)

转载 作者:行者123 更新时间:2023-12-02 09:27:19 25 4
gpt4 key购买 nike

很难总结这个问题,但我会尽力并希望你明白,我有一个实现功能接口(interface)(执行)的枚举,其中执行中唯一的方法是接受两个参数的执行

1:AbstractRepository:spring-jpa接口(interface)

2:字符串

问题是对于每个子枚举,我需要实现执行方法,但不是让它接受 AbstractRepository,我想让它接受扩展 AbstractRepository 的接口(interface)。

这是具有功能接口(interface)的枚举。

package com.deepTech.Familytree.enums;

import com.deepTech.Familytree.domain.ImageBox;
import com.deepTech.Familytree.domain.Person;
import com.deepTech.Familytree.exception.PersonException;
import com.deepTech.Familytree.repository.AbstractRepository;

import java.util.Optional;

import static com.deepTech.Familytree.config.AuthDataConfig.getUser;
import static com.deepTech.Familytree.exception.PersonException.ExceptionType.PERSON_NOT_FOUND;


public enum FileManagementEnumExecution implements Execution {


UPLOAD_PERSON_FILE() {
@Override
// rather than AbstractRepository I want to make it accepts a repository that extends an AbstractRepository
public void execute(AbstractRepository repository, String filename) {
Optional<Person> person1 = (Optional<Person>) repository
.finByTEm(getUser().getEmail());

person1.map(person -> person.copyByImage(new ImageBox(filename)));


repository.save(person1.orElseThrow(() -> new PersonException(PERSON_NOT_FOUND)));
}
},

DELETE_PERSON_FILE() {
@Override
public void execute(AbstractRepository repository, String filename) {
Optional<Person> person1 = (Optional<Person>) repository
.finByTEm(getUser().getEmail());

repository.save(person1
.map(Person::withoutImage)
.orElseThrow(() -> new PersonException(PERSON_NOT_FOUND)));

}
},
UPLOAD_VIP_PERSON_FILE() {
@Override
public void execute(AbstractRepository repository, String filename) {

}
},

DELETE_VIP_PERSON_FILE() {
@Override
public void execute(AbstractRepository repository, String filename) {


}
},
UPLOAD_NEWS_FILE() {
@Override
public void execute(AbstractRepository repository, String filename) {

}
},

DELETE_NEWS_FILE() {
@Override
public void execute(AbstractRepository repository, String filename) {


}
};

}

@FunctionalInterface
interface Execution {
void execute(AbstractRepository repository, String filename);
}

@Service
@RequiredArgsConstructor
public class PersonServiceImpl implements PersonInterface {
...
/* somecode */
...
@Override
public UploadFileResponse uploadPersonFile(Long id, MultipartFile file) {
return fileManagementService.uploadFile(file, id, UPLOAD_PERSON_FILE, personRepository);

}
...
/* somecode */
...
}

这里是 FileManagementService 类

@Service
@RequiredArgsConstructor
public class FileManagementService {
...
/* somecode */
...
public UploadFileResponse uploadFile(MultipartFile file, Long id, SsssEnum ssssEnum, AbstractRepository neo4jRepository) {
String fileName = fileStorageService.storeFile(file);

String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName)
.toUriString();

FileManagementEnumExecution.execute(neo4jRepository, fileName);

return new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize());
}
...
/* somecode */
...
}

有人可以帮忙吗?

最佳答案

如果类实现了某个接口(interface),则它不能指定比接口(interface)更具体的方法参数类型,因为类实例可以安全地向上转换为接口(interface)类型,并且可以使用接口(interface)中指定的类型的参数来调用方法。查看Liskov substitution principle了解更多信息。

要让实现指定某些参数和方法的类型,您应该添加相应的 type parameters到您的界面。以下是根据您的具体情况执行此操作的方法:

@FunctionalInterface
public interface Execution<T extends AbstractRepository> {
void execute(T repository, String fileName);
}

当您实现此接口(interface)时,您可以使用实际类型或其他类型参数来指定类型参数。在您的情况下,如果所有 FileManagementExecution 接受相同类型的存储库,您应该使用实际类型:

public enum FileManagementExecution implements Execution<ConcreteReprisitory> {
UPLOAD_PERSON_FILE() {
@Override
public void execute(ConcreteReprisitory repository, String fileName) {
//TODO
}
},
DELETE_PERSON_FILE() {
@Override
public void execute(ConcreteReprisitory repository, String fileName) {
//TODO
}
}
// other enum constants
}

如果 FileManagementExecution 接受不同类型的存储库,您还应该向 FileManagementExecution 添加类型参数。不幸的是,Java doesn't support generic enums ,所以在这种情况下,你必须使用常规类:

public abstract class FileManagementExecution<T extends AbstractRepository> implements Execution<T> {
private FileManagementExecution() {}

public static final FileManagementExecution<ConcreteReprisitory1> UPLOAD_PERSON_FILE =
new FileManagementExecution<ConcreteReprisitory1>() {
@Override
public void execute(ConcreteReprisitory1 repository, String fileName) {
//TODO
}
};
public static final FileManagementExecution<ConcreteReprisitory2> DELETE_PERSON_FILE =
new FileManagementExecution<ConcreteReprisitory2>() {
@Override
public void execute(ConcreteReprisitory2 repository, String fileName) {
//TODO
}
};
// other constants
}

为了使代码更简洁,您可以将抽象类替换为接口(interface)1:

public interface FileManagementExecution<T extends AbstractRepository> extends Execution<T> {
FileManagementExecution<ConcreteReprisitory1> UPLOAD_PERSON_FILE =
((repository, fileName) -> TODO());
FileManagementExecution<ConcreteReprisitory2> DELETE_PERSON_FILE =
((repository, fileName) -> TODO());
// other constants
}
<小时/>

1 如果您这样做,您将无法禁止实现此接口(interface)。

关于java - 如何在每个子枚举中实现具有不同第一个参数的功能接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58256642/

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