在Java中使用类型推断和泛型方法
我有一个班的人和两个班的男、女延伸人: 在Person中,有一个字段sex可以区分子类,但Person也可以使用 我有一个方法foo,它可以返回Person类型的对象,男性或女性。是否应该使用泛型方法实现返回类型 诸如此类:在Java中使用类型推断和泛型方法,java,generics,Java,Generics,我有一个班的人和两个班的男、女延伸人: 在Person中,有一个字段sex可以区分子类,但Person也可以使用 我有一个方法foo,它可以返回Person类型的对象,男性或女性。是否应该使用泛型方法实现返回类型 诸如此类: public <T> foo(Sex sex) { if (sex=Sex.M) return new Male(); else if (sex=Sex.F) return new Female(); el
public <T> foo(Sex sex) {
if (sex=Sex.M)
return new Male();
else if (sex=Sex.F)
return new Female();
else
return new Person();
}
编辑:
做:
public Person foo(Sex sex) {
if (sex=Sex.M)
return new Male();
else if (sex=Sex.F)
return new Female();
else
return new Person();
}
基本上,我可以使用以男性或女性声明的方法,即使它们是在子类中声明的?因为测试属于个人类型。每个孩子都是父母 只需将您的声明更改为 公众人物性别{ 然后再次测试你能做什么
Person test = foo(sex);
请注意,因为您不知道从foo方法接收到哪个子对象,所以在对其进行操作之前,您需要检查该操作是否特定于子对象
编辑:
主要来说,我可以使用男性或女性声明的方法,即使它们是在子类中声明的?因为测试是Person类型的
这就是我作为注释添加的内容。您不能直接使用。您只能使用来自父级的常用内容变量和方法。如果您想从子级执行某些特定调用,则需要将测试强制转换为该特定子类型
像这样的
public static void main(String[] args){
Person test = foo(sex);
if(test instanceof Male) {
Male m = (Male) test;
// use m as male
}
}
为什么我使用男性的测试实例只是为了在其他类型的情况下避免强制转换失败。每个孩子都是父母 只需将您的声明更改为 公众人物性别{ 然后再次测试你能做什么
Person test = foo(sex);
请注意,因为您不知道从foo方法接收到哪个子对象,所以在对其进行操作之前,您需要检查该操作是否特定于子对象
编辑:
主要来说,我可以使用男性或女性声明的方法,即使它们是在子类中声明的?因为测试是Person类型的
这就是我作为注释添加的内容。您不能直接使用。您只能使用来自父级的常用内容变量和方法。如果您想从子级执行某些特定调用,则需要将测试强制转换为该特定子类型
像这样的
public static void main(String[] args){
Person test = foo(sex);
if(test instanceof Male) {
Male m = (Male) test;
// use m as male
}
}
为什么我使用test instanceof Male只是为了避免其他类型的cast失败。您在这里利用了继承,不需要混合泛型。您可以简单地将Person定义为返回类型-您也可以返回男性和女性实例,因为它们也是Person 然后一切都变得清晰起来:
Person test = foo(sex);
您在这里利用了继承,不需要混合泛型。您可以简单地将Person定义为返回类型-您也可以返回男性和女性实例,因为它们也是Person 然后一切都变得清晰起来:
Person test = foo(sex);
这里不需要泛型,这里Person是男女的超类。
所以,在需要的地方,在声明中使用Person。以后,它总是可以容纳子类实例
以下各项在所有情况下均属罚款—
public Person foo(Sex sex) {
if (sex="m")
return new Male();
else if (sex="f")
return new Female();
else
return new Person();
}
这是因为以下所有作业都是正确的
Person a;
a = new Person(); //correct
a = new Male(); //correct
a = new Female(); //correct
这里不需要泛型,这里Person是男女的超类。
所以,在需要的地方,在声明中使用Person。以后,它总是可以容纳子类实例
以下各项在所有情况下均属罚款—
public Person foo(Sex sex) {
if (sex="m")
return new Male();
else if (sex="f")
return new Female();
else
return new Person();
}
这是因为以下所有作业都是正确的
Person a;
a = new Person(); //correct
a = new Male(); //correct
a = new Female(); //correct
首先,我认为Person类不应该是可实例化的。是否有任何用例需要创建Person类型而不是Male或Femal类型的对象
将Person作为一个具体的类,您试图使用代码重用,这在面向对象编程中是一种糟糕的做法
喜欢组合而不是继承
他们说
无论如何,使用您的解决方案还有另一个问题:您可能存在抽象泄漏。超类不应该知道可用子类的任何可能类型。如果方法foo位于Person类中,则它正面临此问题
最后,泛型对您没有帮助。您需要检查您的设计。正如有人在对您的问题的评论中所建议的,一个可能的优雅解决方案应该是:
abstract class Person {
// Omissis
public abstract String sex();
// Omissis
}
class Male {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Male of() {
return new Male();
}
}
class Female {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Femaleof() {
return new Female();
}
}
class PersonFactory {
public Person build(String sex) {
if ("M".equals(sex) return new Male();
else return new Female();
}
public Male male() {
return new Male();
}
public Female female() {
return new Female();
}
}
因此,如果您需要一种方法来创建新的男性或女性,您可以有一个专用类型,一个工厂,如下所示:
abstract class Person {
// Omissis
public abstract String sex();
// Omissis
}
class Male {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Male of() {
return new Male();
}
}
class Female {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Femaleof() {
return new Female();
}
}
class PersonFactory {
public Person build(String sex) {
if ("M".equals(sex) return new Male();
else return new Female();
}
public Male male() {
return new Male();
}
public Female female() {
return new Female();
}
}
您可以使用静态方法直接在这两个子类中定义,而不是专门用于构建男性和女性的类型。这将使您的设计与新类型的人的添加接近
显然,男性或女性的所有行为也应该对person可用,这意味着您可能需要person类中更抽象的方法
干杯。首先,我认为Person类不应该是实例化的。是否有任何用例需要创建Person类型的对象,而不是Male或Femal类型的对象
把人作为一个整体
在te类中,您试图使用代码重用,这在面向对象编程中是不好的做法
喜欢组合而不是继承
他们说
无论如何,使用您的解决方案还有另一个问题:您可能存在抽象泄漏。超级类不应该知道可用子类的可能类型。如果方法foo位于Person类中,那么它正好遇到了这个问题
最后,泛型对你没有帮助。您需要检查您的设计。正如有人在对您的问题的评论中所建议的,一个可能的优雅解决方案应该是:
abstract class Person {
// Omissis
public abstract String sex();
// Omissis
}
class Male {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Male of() {
return new Male();
}
}
class Female {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Femaleof() {
return new Female();
}
}
class PersonFactory {
public Person build(String sex) {
if ("M".equals(sex) return new Male();
else return new Female();
}
public Male male() {
return new Male();
}
public Female female() {
return new Female();
}
}
因此,如果您需要一种方法来创建新的男性或女性,您可以有一个专用类型,一个工厂,如下所示:
abstract class Person {
// Omissis
public abstract String sex();
// Omissis
}
class Male {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Male of() {
return new Male();
}
}
class Female {
// Omissis
public String sex() {
return "M";
}
// Omissis
public static Femaleof() {
return new Female();
}
}
class PersonFactory {
public Person build(String sex) {
if ("M".equals(sex) return new Male();
else return new Female();
}
public Male male() {
return new Male();
}
public Female female() {
return new Female();
}
}
您可以使用在这两个子类中直接定义的静态方法,而不是专门用于构建雄性和雌性的类型。这将使你的设计与新类型的人的增加紧密相连
显然,男性或女性的所有行为也应该对person可用,这意味着您可能需要person类中更抽象的方法
干杯。您也可以使用重载方法并删除thr sex partsex=m,我认为您应该更正问题的这一部分。此外,性别被宣布为性别类型;它不是一个字符串。您也可以使用重载方法并删除thr sex partsex=m,我认为您应该更正问题的这一部分。此外,性别被宣布为性别类型;这不是一个字符串。但从那以后,你就只有Person的方法和属性,而不是child,或者我错了吗?@MarcelHöll是的。你是对的。加上这句话作为我的回答。天哪!一瞬间@ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ 通过将cast转换为Male,我看到现在可以使用子cases中定义的方法。但是存储在雄性子类中的信息呢?它有一个不同于Person的构造函数,比如,一个int字段beardLength@Pleasant94你将在创造男性时使用foo方法:但从那时起,你只拥有Person而不是child的方法和属性,还是我错了?@MarcelHöll是的。你是对的。加上这句话作为我的回答。天哪!一瞬间@ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ 通过将cast转换为Male,我看到现在可以使用子cases中定义的方法。但是存储在雄性子类中的信息呢?它有一个不同于Person的构造函数,比如,一个int字段beardLength@Pleasant94在创建男性时,您将在foo方法中使用:所以主要我可以做:Person test=foosex;试验方法在马尔;“它行得通吗?”@Pleasant94不,不行。如果你做Maletest.methodInMale;,它可能会起作用;,虽然如果你有一个女演员,很明显你会有演员失败的风险test@Deltharis我应该用什么来进行这种类型的推理,或者我应该用什么方法来解决这个问题?因为我不知道返回的类型。谢谢@Deltharis指出它。如果一个方法只属于子类而不属于父类,正如您在更新的部分中所要求的那样,它将给您一个编译错误。@Pleaseant94在强制转换之前,您需要使用instanceof运算符来确保该类型。例如-如果myObj instanceof Male{…//Cast here},那么主要我可以做:Person test=foosecx;试验方法在马尔;“它行得通吗?”@Pleasant94不,不行。如果你做Maletest.methodInMale;,它可能会起作用;,虽然如果你有一个女演员,很明显你会有演员失败的风险test@Deltharis我应该用什么来进行这种类型的推理,或者我应该用什么方法来解决这个问题?因为我不知道返回的类型。谢谢@Deltharis指出它。如果一个方法只属于子类而不属于父类,正如您在更新的部分中所要求的那样,它将给您一个编译错误。@Pleaseant94在强制转换之前,您需要使用instanceof运算符来确保该类型。如果myObj instanceof Male{…//Cast here}我不太理解你对hisfoo方法的反对,因为你基本上复制了它,减少了人员实例化和清理,只是提到它在正确的工厂类中。函数foo的问题是它的位置。不应在Person类型中声明它。我不喜欢工厂阶级,但如果他需要一个地方来建造人,我认为没有其他解决办法。我的解决方案也将人物转换为抽象类型这是最重要的改变。我不知道他说的人物类型在哪里。我的意思是,它可能在那里,但也没有理由怀疑。这个构造函数甚至在另一个包中,我用这个例子只是为了说明我的问题。好的。我回答的重点是你不应该创建Person类型的对象。我不太理解你对hisfoo方法的反对,因为你基本上复制了它,减少了Person实例化和清理,只是提到它在正确的工厂类中。问题是
函数foo是它的位置。不应在Person类型中声明它。我不喜欢工厂阶级,但如果他需要一个地方来建造人,我认为没有其他解决办法。我的解决方案也将人物转换为抽象类型这是最重要的改变。我不知道他说的人物类型在哪里。我的意思是,它可能在那里,但也没有理由怀疑。这个构造函数甚至在另一个包中,我用这个例子只是为了说明我的问题。好的。我回答的重点是,您不应该能够创建Person类型的对象。