[英]How can I instantiate a specific sub-type for a @RequestBody parameter based on the requested URI for a Spring MVC controller method?
[英]How can i prevent explicit casting if you want to use properties of the sub-type?
因此,編譯器會在我進行顯式轉換時抱怨。 我可以通過使用@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寵物類一個getType()方法,該方法返回一個枚舉。 使用這個枚舉,我可以刪除“ instanceof”,但是演員表仍然存在。
我想念什么嗎?
如果這是一個現實世界中的問題,看守者將根據寵物的外觀識別出他擁有哪種寵物。 盡管“ instance of”是一種查看方式,但您可能需要考慮根據需要直接使用子類型重載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
。 盡管實例化的好壞有待商,,但應該盡可能讓對象本身告訴我它的需求,否則整個多態概念很快就會變得很毛茸茸。
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();
}
}
讓我們說清楚:如果不將類型轉換為子類類型,則無法調用特定於子類的方法。
現在,讓我提出另一種方法。 在超類中定義方法takeCare()
,並讓子類通過調用特定於子類的幾種特定方法來實現它。 然后從CareTaker#takeCare()
,僅調用takeCare()
方法,而無需進行類型轉換。
可以使用其他幾種替代方法來解決這種情況。
這是使用接口和反射進行操作的方式。 請注意,每種寵物類型僅調用接口方法。 它也可以擴展為調用其他方法。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PetProblem {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Dog dog = new Dog();
caretaker.takeCare(dog);
System.out.println("\nNow do it for the cat\n");
Cat cat = new Cat();
caretaker.takeCare(cat);
}
}
interface CuteCat {
void letOutside();
void letInside();
void removeTick();
}
interface CuteDog {
void goForAWalk();
void tellHimWhatHeIs();
}
interface CutePet {
default void pet() {
System.out.println("The cute pet gets some pets");
}
}
class Cat implements CutePet, CuteCat {
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 implements CutePet, CuteDog {
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(Object pet) {
Class<?>[] ifss = pet.getClass().getInterfaces();
for (Class<?> ifs : ifss) {
Method[] methods = ifs.getDeclaredMethods();
for (Method m : methods) {
try {
m.invoke(pet);
}
catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
但是請注意,使用接口並具有這樣一種方法(該方法可以用於所有寵物)更容易。 這是一個例子。 由於貓和狗都需要吃飯,因此可以為每個對象實現通用方法feedMe()
。
public class AnimalShelter {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Dog dog = new Dog();
Cat cat = new Cat();
caretaker.feedThePets(dog);
caretaker.feedThePets(cat);
}
}
interface SupperTime {
void feedMe();
}
class Caretaker {
public void feedThePets(SupperTime pet) {
pet.feedMe();
}
}
class Dog implements SupperTime {
public void feedMe() {
System.out.println("Oh boy, Kibbles n' Bits");
}
}
class Cat implements SupperTime {
public void feedMe() {
System.out.println("Yum. Purina Cat Chow");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.