98_面向对象(多态-概念)
多态:可以理解事物存在的多种体现形态。
重载和覆盖就是函数的多态体现。
人:男人,女人。这就是人的多态。
动物:猫,狗
猫 x=new 猫();
动物 x=new 猫();
1,多态的基本体现
父类的引用指向了自己的子类对象。
2,多态的前提
必需是类与类之间有关系。要么继承,要么实现。
通常还有一个前提,存在覆盖。
3,多态的好处
多态的出现大大的提高程序的扩展性。
多态的弊端:
提高了扩展性,但是只能使用父类的引用,访问父类中的成员。
4,多态的应用。
99_面向对象(多态-扩展性)
1,多态的基本体现
父类的引用指向了自己的子类对象。
父类的引用也可以接受自己的
动物:猫,狗。
class Animal
{
void eat()
{
}//错误,eat吃什么,不确定。
}
改成抽象:
abstract class Animal
{
public abstract void eat();吃是一种多态。
}
class Cat extends Animal
{
public void eat()//函数覆盖
{
system.out.println(吃鱼);
}
public void catchMouse()
{
system.out.println(抓老鼠);
}
}
class Dog extends Animal
{
public void eat()
{
system.out.println(吃骨头);
}
public void kanJia()
{
system.out.println(看家);
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Cat c=new Cat();
c.eat();打印吃鱼。
Dog d=new Dog();
d.eat();打印吃骨头。
Cat c1=new Cat();
c1.eat();打印吃鱼。
Cat c2=new Cat();
c2.eat();打印吃鱼。
}
封装方法.eat()。
class DuoTaiDemo
{
public static void main(String[] args)
{
Cat c=new Cat();
Cat c1=new Cat();
function(c1);打印吃鱼。
function(new Dog());打印吃骨头
}
public static void function(Cat c)
{
c.eat();
}
public static void function(Dog d)
{
d.eat();
}
一年后,还有养猪。
abstract class Animal
{
public abstract void eat();//吃是一种多态。
}
class Cat extends Animal
{
public void eat()
{
system.out.println(吃鱼);
}
public void catchMouse()
{
system.out.println(抓老鼠);
}
}
class Dog extends Animal
{
public void eat()
{
system.out.println(吃骨头);
}
public void kanJia()
{
system.out.println(看家);
}
}
//养猪
class Pig extends Animal
{
public void eat()
{
system.out.println(饲料);
}
public void gongDi()
{
system.out.println(拱地);
}
}
public static void function(Cat c)
{
c.eat();
}
public static void function(Dog d)
{
d.eat();
//添加了猪的吃。
public static void function(Pig p)
{
p.eat();
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Cat c=new Cat();
Cat c1=new Cat();
function(c1);//打印吃鱼。
function(new Dog());//打印吃骨头
function(new Pig());//打印饲料
}
对比:
abstract class Animal
{
public abstract void eat();吃是一种多态。
}
class Cat extends Animal
{
public void eat()
{
system.out.println(吃鱼);
}
public void catchMouse()
{
system.out.println(抓老鼠);
}
}
class Dog extends Animal
{
public void eat()
{
system.out.println(吃骨头);
}
public void kanJia()
{
system.out.println(看家);
}
}
class Pig extends Animal
{
public void eat()
{
system.out.println(饲料);
}
public void gongDi()
{
system.out.println(拱地);
}
}
public static void function(Cat c)
{
c.eat();
}
public static void function(Dog d)
{
d.eat();
//添加了猪的吃。
public static void function(Pig p)
{
p.eat();
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Animal c=new Cat();//为什么可以这样呢???一个对象具备多种形态造成的。c是猫,也是动物。把动物变成了具体的猫。
c.eat(); //打印吃鱼。子类覆盖父类eat()
}
多态实例代码:
abstract class Animal {
public abstract void eat();//吃是一种多态。
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void kanJia() {
System.out.println("看家");
}
}
class Pig extends Animal {
public void eat() {
System.out.println("饲料");
}
public void gongDi() {
System.out.println("拱地");
}
public static void function(Animal a)//这时,变成了Animal a=new Cat()
{
a.eat();
}
}
class Anim {
public static void main(String[] args) {
Pig.function(new Cat());//注意:不是function(new Cat);
Pig.function(new Dog());//打印:吃骨头。
Pig.function(new Pig());
}
}
3,多态的好处
多态的出现大大的提高程序的扩展性。
100_面向对象(多态-转型)
public class Anim {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
// 类型提升。 byte b=1;int x=b;把猫提升为动物。向上转型。转成父类型。动物具备了猫的属性。
Cat c = (Cat) a;//强制把动物转换成猫
c.catchMouse();
}
}
打印:
吃鱼
抓老鼠
人物举例:
毕姥爷 x=new 毕老师();毕老师变成了毕姥爷。
x.讲课();虽然变成了毕姥爷,但是运行的是毕老师讲课的内容,讲java内容。
毕老师 y=(毕老师)x;再把毕姥爷变回成毕老师。
y.看电影();然后毕老师可以陪朋友去看电影了。哈哈。。。
运用instanceof实例化来判断是不是属于该类。
public class Anim {
public static void main(String[] args) {
Pig.function(new Cat());
Pig.function(new Dog());
}
}
abstract class Animal {
public abstract void eat();//吃是一种多态。
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void kanJia() {
System.out.println("看家");
}
}
class Pig extends Animal {
public void eat() {
System.out.println("饲料");
}
public void gongDi() {
System.out.println("拱地");
}
public static void function(Animal a)//这时,变成了Animal a=new Cat()
{
a.eat();
if (a instanceof Animal)//a的实例化是Cat吗?a属于Animal吗?
{
System.out.println("haha");
} else if (a instanceof Cat)//a的实例化是Cat吗?
{
Cat c = (Cat) a;
c.catchMouse();
} else if (a instanceof Dog)//a的实例化是Dog吗?
{
Dog c = (Dog) a;
c.kanJia();
}
}
}
打印:
吃骨头
haha
看家
haha
102_面向对象(多态中成员的特点)
重点!!!
在多态中,成员函数的特点
在编译时期:查阅引用型变量所属的类中是否有调用的方法。如果有,编译通过。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
public class Anim {
public static void main(String[] args) {
Zi z = new Zi();
z.method1();//zi method_1
z.method2();//fu method_2
z.method3();//zi method_3
}
}
class Fu {
void method1() {
System.out.println("fu method_1");
}
void method2() {
System.out.println("fu method_2");
}
}
class Zi extends Fu {
void method1() {
System.out.println("zi method_1");//Zi_1把父类的Zi_1覆盖了。
}
void method3() {
System.out.println("zi method_3");
}
}
对比:
class DuoTaiDemo
{
public static void main(String[] args)
{
Fu f=new Zi();//父类引用子类
f.mothod1();//zi method_1。编译通过,父类有该方法;运行看右边,结果是子类的
f.mothod2();//fu method_2
}
}
对比:
class DuoTaiDemo
{
public static void main(String[] args)
{
Fu f=new Zi();
f.mothod1();
f.mothod2();
f.mothod3();//编译失败。编译的时候对象Zi还没产生,系统会找Fu中,发现没有mothod3.
}
}
面试用:
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
public class Anim {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);//打印是父类的num=5,成员变量没有覆盖操作
Zi z = new Zi();
System.out.println(z.num);
}
}
class Fu {
int num = 5;//成员变量num=5
void method1() {
System.out.println("fu method_1");
}
void method2() {
System.out.println("fu method_2");
}
}
class Zi extends Fu {
int num = 8;
void method1() {
System.out.println("zi method_1");//Zi_1把父类的Zi_1覆盖了。
}
void method3() {
System.out.println("zi method_3");
}
}
打印:
5
8
面试用:
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。静态随着类加载
public class Anim {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);//打印是父类的num=5,num对象也是静态的
f.method1();//fu method_1。mothod的是静态,f.mothod1()相当于类.静态方法,就是类名调用。
Zi z = new Zi();
System.out.println(z.num);
}
}
class Fu {
static int num = 5;//成员变量num=5
static void method1() {
System.out.println("fu method_1");
}
void method2() {
System.out.println("fu method_2");
}
}
class Zi extends Fu {
int num = 8;
static void method1() {
System.out.println("zi method_1");//Zi_1把父类的Zi_1覆盖了。
}
void method3() {
System.out.println("zi method_3");
}
}
打印:
5
fu method_1
8
103_面向对象(多态的主板示例)
需求:
电脑运行实例,
电脑运行基于主板。
主板要实现多功能
public class Anim {
public static void main(String[] args) {
MainBoard mb=new MainBoard();
mb.run();
mb.usePCI(null);//这句自动跳过
mb.usePCI(new NetCard());//mb.usePCI.NetCard(),为什么不可以这样?NetCard没有被public修饰
}
}
interface PCI {
public void open();
public void close();//父类抽象的方法
}
class MainBoard {
public void run() {
System.out.println("mainboard run");
}
public void usePCI(PCI p)//PCI p=new NetCard()。接口型引用指向自己的子类对象。
{
if (p != null)//检测插槽是否为空。
{
p.open();
p.close();
}
}
}
class NetCard implements PCI//implements实现端口
{
public void open()//覆盖了父类方法
{
System.out.println("netcard open");
}
public void close() {
System.out.println("netcard close");
}
}
打印:
mainboard run
netcard open
netcard close
104_面向对象(多态的扩展示例)
需求:数据库的操作。
数据是:用户信息。
1,连接数据库JDBC Hinernate
2,操作数据库。
c create r read u update d delete
3,关闭数据库连接。
class UserInfoByJDBC
{
pulic void add(User user)
{
1,JDBC连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
pulic void delete(User user)
{
1,连JDBC接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class DBOperate
{
public static void main(String[] args)
{
UserInfoByJDBC ui =new UserInfoByJDBC();
ui.add(user);
ui.delete(user);
}
}
通过Hibernate连接。
class UserInfoByHibernate
{
pulic void add(User user)
{
1,Hibernate连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
pulic void delete(User user)
{
1,Hibernate接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class DBOperate
{
public static void main(String[] args)
{
UserInfoByHibernate ui =newUserInfoByHibernate();
ui.add(user);
ui.delete(user);
}
}
两次变化,主函数都需要改变ui的变量类型。如何降低耦合性。?
interface UserInfoDao//接口
{
public void add(User user);
public void delete(User user);
}
class UserInfoByJDBC implements UserInfoDao
{
pulic void add(User user)//覆盖接口
{
1,JDBC连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
pulic void delete(User user)
{
1,连JDBC接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class DBOperate
{
public static void main(String[] args)
{
UserInfoDao ui=new UserInfoByJDBC();
ui.add(user);
ui.delete(user);
}
}
105_面向对象(Object类-equals())
object是所有对象的直接后者间接父类,传说中的上帝。
该类中定义的肯定是所有对象都具备的功能。
class Demo//隐藏了extends object
{
Demo()
{
//隐藏了super();
}
java中,任何对象具备比较两个对象是否相同的功能:equals
其实equals其实相当于比较地址值
class Demo
{
}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo();
Demo d2=new Demo();
Demod3=d1;//d3是媒介
System.out.println(d1.equals(d2));//打印false
System.out.println(d1.equals(d3));//打印true。这个equals接受的是Demo类型
System.out.println(d1==d2);//打印false。其实equals其实相当于比较地址值。
System.out.println(d1==d3);//打印true
Person p1=new Person();
Person p2=new Person();
system.out.println(people+p1.equals(p2));打印people:true。这个equals接受是Person类型
}
}
}
Person类型和Demo类型都是object的子民。
而equals(Object obj)定义的是object的类型,故它的子民都是可以调用它。
class Demo
{
private int num;
Demo(int num)//构造函数
{
this.num=num;
}
public boolean compare(Demo d)
{
return this.num==d.num;//比较的是数值,而不是地址。
}
}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo(4);
Demo d2=new Demo(6);
System.out.println(d1.compare(d2));//false
}
}
}
Object类中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能时,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。
class Demo
{
private int num;
Demo(int num)
{
this.num=num;
}
public boolean equals(Object obj)
{
return this.num==obj.num;//变量num在Object的类中,找不到。
}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo(4);
Demo d2=new Demo(6);
System.out.println(d1.equals(d2));//编译错误。
}
}
}
对比:
class Demo
{
private int num;
Demo(int num)
{
this.num=num;
}
public boolean equals(Object obj)
//此时把Object obj=d2;相当于Object obj=new Demo();这时相当于多态的表现形式。
{
Demo d=(Demo)obj;//把上帝类Object的obj对象,强制转换为Demo型
return this.num==d.num;//这时,就可以调用d.num
}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo(4);
Demo d2=new Demo(4);
System.out.println(d1.equals(d2));//打印true
}
}
类型转换异常。
class Demo
{
private int num;
Demo(int num)
{
this.num=num;
}
public boolean equals(Object obj)
{
Demo d=(Demo)obj;
return this.num==d.num;
}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo(4);
Demo d2=new Demo(5);
Person p=new Person();
System.out.println(d1.equals(p));//运行报错。ClassCastException类型转换异常。
}
}
instanceof 判断类型
class Demo
{
private int num;
Demo(int num)
{
this.num=num;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Demo))//instanceof obj指向的是Demo吗?不是,返回false
return false;
Demo d=(Demo)obj;
return this.num==d.num;
}
class ObjectDemo
{
public static void main(String p[] args)
{
Demo d1=new Demo(4);
Demo d2=new Demo(5);
Person p=new Person();
System.out.println(d1.equals(p));//打印false
}
}
106_面向对象(Object类toString())
toString()函数:默认返回的内容是“对象所属的类名+@+对象的哈希值(十六进制)”
Object中有专门打印哈希值的函数hashCode():
class Demo{}
class ObjectDemo
{
public static void main(Stringp[] args)
{
Demo d1=new Demo();
Class c=d1.getClass();//c获取d1对象所属的类Demo
//c.getName()返回c的名称,Integer.toHexString(d1.hashCode())这个对象的哈希值强制转换为16进制
System.out.println(c.getName()+@+Integer.toHexString(d1.hashCode()));//打印Demo@c17164
System.out.println(d1.toString);//Demo@c17164
}}
总结:
toString()相当于
getClass().getName() + '@' +Integer.toHexString(hashCode())
重写toString
public class PackageOne {
public static void main(String[] args) {
System.out.println(new ToStringDemo().toString());//tostring
}
}
class ToStringDemo{
//重写(覆盖)原来的toString()
@Override
public String toString() {
return "tostring";
}
}