Java三大特性有封装、继承、多态。
前面我们已经学过了封装和继承,今天学习多态,如需前面内容的可自行查看。
多态是继封装、继承之后,面向对象的第三大特性
生活中,比如交通工具的种类可以分为飞机、汽车、轮船
再比如交通工具的运行方式飞机运行方式是飞在天上、汽车是在马路上开、轮船是在海上行驶
可见,同一行为,通过不同的事物,可以体现出来的不同的形态
多态,描述的就是这样的状态。
多态性是面向对象的三大特征之一,同一行为,通过不同的事物,可以体现出来的不同的形态。
提个概念,编译器类型指的是‘=’左边的类型,运行期类型指的是‘=’右边的类型。
当有继承关系时,可能发生编译期类型和运行期类型不同的情况,即编译期类型是父类类型,运行期类型是子类类型。
即:父类引用指向子类对象
例如:
//动物类
public class Animal {
private String name;
public Animal() {
// TODO Auto-generated constructor stub
this.name = "动物";
}
public void eat() {
System.out.println("动物在吃");
}
static void look() {
System.out.println("动物在看");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//狗类
public class Dog extends Animal {
private String name;
public Dog() {
// TODO Auto-generated constructor stub
this.name = "狗";
}
public void eat() {
System.out.println("狗在吃");
}
public void bite() {
System.out.println("狗咬人");
}
static void look() {
System.out.println("狗在看");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//测试类:
public class Demo {
public static void main(String[] args) {
// 父类对象指向子类引用
Animal animal = new Dog();
// 如果子类中重写了父类的方法,按照子类重写的方法执行
animal.eat();
// 子类自己扩展的方法,不能调用
// animal.bite();
// 调用父类和子类同名的静态方法,调用的是父类的静态方法
animal.look();
}
}
接着上述的案例,如果我们有个方法需要分别调用他们同名的方法,应该怎么做呢?
比如:在Demo类中有个doing()方法,我想要传进来的对象,让他们都执行他们的eat()这个方法,此时,我们就需要利用方法参数多态性。
我们只需要把形参的类型定义成父类的类型,我们可以利用上面提到过的验证(当父类引用调用子类对象时,调用重写的方法,是执行子类的重写后方法)。
在一个方法的形参类型你设成父类类型,你传入一个实参对象,如果是一个子类的对象就相当于上述的父类引用调用子类对象,如果传入的是父类对象那就是正常的编译器类型等于运行期类型情况,正常调用。
如此,我们就实现了形参的多态性,在很大程度上减少了代码的重复性,也提高了代码的扩展性。
class Demo{
void doing(Animal a){
a.eat();
}
}
上述情况,只是描述对于一些子类重写父类方法的调用,在第一个案例中,我们知道父类引用指向子类对象时,没有办法调用子类扩展的方法,那我们应该怎么做了?
此时,我们就需要用到我们在学习数据类型时的一个概念,强制转换,将父类引用强制转换成子类的类型。
注意:强制转换,只能是将父类类型转换成运行期类型,不能是别的类型。
不仅父类引用可以强制转换成子类的类型,子类的引用也可以强制转换成父类的类型。
从造型方向上看,可分为:
(1)向上造型 –又称自动类型提升
即父类引用指向子类对象,将子类对象向上造型成为父类类型。
作用是:提高程序的扩展性。
(2)向下造型 –又称向下转型
即将子类对象强制转换成父类类型
作用:实现子类扩展方法的调用。
例如:接着上述例子
//父类引用指向子类对象
Animal animal=new Dog();
Dog dog = (Dog)animal; //将父类引用强制转换成子类的类型
dog.look(); //此时调用的子类的静态方法
dog.bite(); //可以调用子类扩展的方法
//子类引用指向子类对象
Dog dog1 = new Dog();
Animal a = (Animal)dog1; //将子类引用转换成父类类型
a.eat(); //调用的是子类的方法
a.look(); //调用的是父类的静态方法
//a.bite(); //子类扩展的方法不能调用
使用instanceof操作符来判断一个对象的运行期类型,即用来在运行时指出对象是否是特定类的一个实例。
语法:
对象名称 instanceof 类型;
返回值类型:布尔类型
Dog dog1 = new Dog();
Animal a = (Animal)dog1;
System.out.println(a instanceof Animal);
//结果:
true
我使用的是遗留数据库,所以我无法控制数据模型。他们使用了很多多态链接/连接表,就像这样createtableperson(per_ident,name,...)createtableperson_links(per_ident,obj_name,obj_r_ident)createtablereport(rep_ident,name,...)其中obj_name是表名,obj_r_ident是标识符。因此链接的报告将按如下方式插入:insertintoperson(1,...)insertintoreport(1,...)insertintoreport(2,...)insertint
有这个:classEventtrueenduser=User.create!我可以:Event.create!(:historizable=>user)但我不能:Event.where(:historizable=>user)#Mysql2::Error:Unknowncolumn'events.historizable'in'whereclause'我必须改为这样做:Event.where(:historizable_id=>user.id,:historizable_type=>user.class.name)更新重现问题的代码:https://gist.github.com/fg
我有一个UserType和一个可以是Writer或Account的userable。对于GraphQL,我想也许我可以像这样使用UserableUnion:UserableUnion=GraphQL::UnionType.definedoname"Userable"description"AccountorWriterobject"possible_types[WriterType,AccountType]end然后像这样定义我的用户类型:UserType=GraphQL::ObjectType.definedoname"User"description"Auserobject"fie
我试图在没有任何重复的情况下显示多态关系列表。我有一个StoreViews表,其中包含一个名为viewable的多态字段(因此我的表中有一个viewable_id和viewable_type列)。现在我想显示View,每个多态关系只显示一次,没有重复。@views=StoreView..distinct(:viewable_id).distinct(:viewable_type).order("created_atDESC").limit(10)因此,如果StoreViews中有两条记录,并且都具有相同的可见关系,@views应该只返回最近的一条。然而,事实并非如此。
我在两个模型之间有一个现有的has_many关系-称它们为“汽车”和“乘客”-在我的生产环境中有几千个“乘客”属于几百个“卡片”。我正在添加另一个模型,称之为“火车”,我想将汽车和乘客之间现有的has_many关系更改为多态关系,将每位乘客与汽车或火车相关联。我的迁移应该是什么样的?我想在迁移时保留数据库中的现有关系,所以我宁愿进行一些表重命名,而不是删除一列以将其替换为另一列。此外,我希望能够在不打开服务器控制台并手动编辑所有记录的情况下执行此操作,这样当我将更改推送到生产环境时,我可以一次性迁移整个数据库。有什么建议吗?TL;DR:如何使用新模型将现有的has_many关系更改为多
我有两个模型(项目和主题)。它们都属于具有has_many关联的第三个模型用户(用户有很多主题和项目)。Item和Theme都有_many:images.图像模型是一个多态关联,因此该表具有列imageable_id和imageable_type。如果我同时拥有一个ID为1的项目和一个ID为1的主题,那么该表将如下所示idimageable_idimageable_type------------------------------------11Item21Theme我正在使用declarative_authorization重写我的数据库的SQL查询,以防止用户访问他们帐户之外的项
如果您有多态的belongs_to关联,那么引用将添加所需的两个列:create_table:productsdo|t|t.references:attachment,:polymorphic=>{:default=>'Photo'}end将添加一个attachment_id列和一个默认值为“Photo”的字符串attachment_type列。这到底是什么意思? 最佳答案 这里是引用方法的文档:http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Ta
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭9年前。Improvethisquestion您知道RubyonRails多态关系的优点和缺点。
我对我得到的多态关联有点困惑。我需要一个Article模型来有一个标题图像和许多图像,但我想要一个单一的图像模型。更令人困惑的是,图像模型是多态的(以允许其他资源拥有许多图像)。我在我的文章模型中使用这个关联:classArticle:imageablehas_many:images,:as=>:imageableend这可能吗?谢谢。 最佳答案 我试过了,但是header_image返回了其中一张图片。仅仅是因为图像表没有指定不同的图像使用类型(header_image与普通图像)。它只是说:imageable_type=Imag
我需要(或者我认为)在我的模型中实现多态关联,但我有问题。看我的情况,就是一个简单的问答系统,逻辑如下:-一个问题可以用N个答案来回答。-答案只能是“文本”异或(一个或另一个,不能同时是两个)“图片”。迁移:classCreateAnswerstruet.timestampsendendendclassCreateAnswerTexts模型*answer.rb*classAnswertrueattr_accessible:answerable_typeendanswer_text.rbclassAnswerText:answerableattr_accessible:contenten