Java基础-面向对象
面向对象入门(续)
1、面向对象(多态--概念)
(1)、多态:可以理解为事物存在的多种体现形式。 例如:
人:男人、女人。 动物:猫、狗。
Eg:
猫 x = new 猫 () ;
动物 x = new 猫 () ;
(2)、特征
- 多态的基本体现:父类的引用指向了自己的子类对象。父类的引用也可以接收自己的子类对象。
- 多态的前提:必须是类与类之间有关系。要么继承,要么实现,还有一个前提:存在覆盖。
- 多态的好处:大大提高了程序的扩展性。(弊端:但是只能使用父类的引用访问父类中的成员。)
-
多态的应用:
/* *动物 *猫、狗 * */ abstract class Animal //抽象类Animal { abstract void eat(); //抽象方法 } class Cat extends Animal //类Cat继承抽象类Animal { public void eat() { System.out.println("吃鱼"); //方法覆盖 } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal //类Dog继承抽象类Animal { public void eat() { System.out.println("吃骨头"); //方法覆盖 } public void kanjia() { System.out.println("看家"); } } class Pig extends Animal //类Pig继承抽象类Animal { public void eat() { System.out.println("饲料"); //方法覆盖 } public void gongDi() { System.out.println("拱地"); } } class DuoTaiDemo //主函数 { public static void main(String[]args) { Cat c = new Cat(); c.eat(); Dog d = new Dog(); d.eat(); function(c); //对象作为函数参数用来传递 function(d); //多态体现。d为Dog类型,传到function(Animal a)里,进行实现多态功能 function(new Pig());//同样进行多态实现功能。 Animal c1 = new Cat();//类型提升,也是多态的表现。 c1.eat(); } public static void function(Cat c) { c.eat(); } public static void function(Animal a) //用父类Animal类的对象作为函数接收参数的类型,用来体现多态机制,提高代码复用性。 { a.eat(); } }
输出结果:
吃鱼
吃骨头
吃鱼
吃骨头
饲料
吃鱼
2、面向对象(多态--转型)
前例中的 Animal a = new Cat(); 我们称为类型提升,也叫向上转型。
如果想要调用猫的特有方法时,如何操作? 强制将父类的引用,转成子类类型,称作向下转型。 例如:
Cat c = (Cat) a ;
c.catchMouse;
但如果这样的话,错误:
Animal a = new Animal();
Cat c = (Cat) a;
千万不要出现以上这样的操作,就是将父类对象转成子类类型,我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换,多态自始至终都是子类对象在做着变化。
3、面向对象(多态成员中的特点)
Eg:
class Fu
{
void method_1()
{
System.out.println("Fu method_1");
}
void method_2()
{
System.out.println("Fu method_2");
}
}
class Zi extends Fu
{
void method_1()
{
System.out.println("Zi method_1");
}
void method_3()
{
System.out.println("Zi method_3");
}
}
class DuoTaiDemo4
{
public static void main(String[]args)
{
Zi z = new Zi();
z.method_1(); //输出Zi method_1
z.method_2(); //输出Fu method_2
z.method_3(); //输出Zi method_3
Fu f = new Fu();
f.method_1(); //输出Zi method_1
f.method_2(); //输出Fu method_2
f.method_3(); //输出错误
}
}
在多态中成员函数的特点:
(1)在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败。
(2)在运行时期:在参阅对象所阅的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
另一个例子:
class Fu
{
int num = 5;
}
class Zi extends Fu
{
int num = 8;
}
class DuoTaiDemo4
{
public static void main(String []args)
{
Fu f = new Zi();
System.out.println(f.num);
Zi z = new Zi();
System.out.println(z.num);
}
}
输出结果:
5
8
在多态中,成员变量的特点:无论编译和运行,都参看左边(引用型变量所属的类)
例:
class Fu
{
static void method_1()
{
System.out.println("Fu method_1");
}
}
class Zi extends Fu
{
static void method_1()
{
System.out.println("Zi method_1");
}
}
class DuoTaiDemo4
{
public static void main(String []args)
{
Fu f = new Zi();
f.method_1();
Zi z = new Zi();
z.method_1();
}
}
程序结果:
Fu method_1
Zi method_1
在多态中,静态成员函数特点: 无论编译还是运行,都参考左边。
4、面向对象(多态的主板示例)
实际小应用
/*
* 需求:
* 电脑运行示例。电脑运行基于主板*/
//未运用多态机制编写的代码,即未改善的代码
class MainBoard //主板
{
public void run() //启动主板
{
System.out.println("mainboard run");
}
public void useNetCard(NetCard c) //主板上的功能,使用网卡(网卡插入)
{
c.open();
c.close();
}
}
class NetCard //网卡
{
public void open() //打开网卡
{
System.out.println("netcard open");
}
public void close() //关闭网卡
{
System.out.println("netcard close");
}
}
class DuoTaiDemo5
{
public static void main(String[]args)
{
MainBoard mb = new MainBoard(); //新建主板对象
mb.run(); //运行主板(主板通电)
mb.useNetCard(new NetCard()); //启动主板上的使用网卡功能,并把网卡插入到主板中
}
}
程序输出结果:
mainboard run
netcard open
netcard close
但以上代码类与类之间耦合性太强。实际中电脑主板与各硬件之间联系的藕带还有一个关键的接口(PCI),如图:
改善后的代码: Eg:
interface PCI //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 NewCard(); 这是接口型引用指向自己的子类对象
{
if(p!=null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI //网卡实现PCI接口
{
public void open() //功能覆盖,启动网卡
{
System.out.println("netcard open!");
}
public void close() //功能覆盖,关闭网卡
{
System.out.println("netcard close!");
}
}
class SoundCard implements PCI //声卡实现PCI接口
{
public void open() //功能覆盖,启动声卡
{
System.out.println("soundcard open!");
}
public void close() //功能覆盖,关闭声卡
{
System.out.println("soundcard close!");
}
}
class DuoTaiDemo5
{
public static void main(String[]args)
{
MainBoard mb = new MainBoard(); //新建主板对象
mb.run(); //启动主板
mb.usePCI(null); //
mb.usePCI(new NetCard()); //在PCI上插入网卡
mb.usePCI(new SoundCard()); //在PCI上插入声卡
}
}
程序结果:
mainboard run!
netcard open!
netcard close!
soundcard open!
soundcard close!
5、面向对象(多态的扩展示例)
以下一段关于数据库操作的伪代码:
/*
*需求:数据库的操作
*1、连接数据库。JDBC、Hibernate
*2、操作数据库:creat、read、update、delete
*3、关闭数据库连接。
* */
class UserInfoByJDBC
{
public void add(User user)
{
1、连接数据库
2、使用sql添加语句添加数据
3、关闭连接
}
public void delete(User user)
{
1、连接数据库
2、使用sql添加语句删除数据
3、关闭连接
}
}
class DBOperate
{
public static void main(String[]args)
{
UserInfoByJDBC ui = new UserInfoByJDBC();
ui.add(user);
ui.delete(user);
}
}
通过观察以上的伪代码我们可以发现问题:若我们不想用JDBC连接数据库,而是Hibernate连接,那么我们又要定义一个新的UserInfoByHibernate类,麻烦,这样设计程序耦合性太强,没考虑到程序的扩展性。
如图:
然而,我们考虑一种新的方法来解决程序类之间的耦合性差问题,增加程序的扩展性。 我们引用一个Dao(date access object)方法,如图:
以下是伪代码: Eg:
interface UserInfoDao
{
public void add(User user);
public void delete(User user);
}
class UserInfoByJDBC implements UserInfoDao
{
1、连接数据库
2、使用sql添加语句删除数据
3、关闭连接
}
class UserInfoByHibernate implements UserInfoDao
{
1、连接数据库
2、使用sql添加语句删除数据
3、关闭连接
}
class DBOperate
{
public static void main(String[]args)
{
UserInfoDao ui = new UserInfoByHibernate();
UserInfoDao ui_1 = new UserInfoByJDBC();
ui.add(user);
ui.delete(user);
ui_1.add(user);
ui_1.delete(user);
}
}
6、面向对象(Object类 ----equal())
Object类:是所有对象的直接或者间接父类,传说中的上帝,该类中定义的肯定是所有对象都具备的功能。
Eg:
class Demo //extends Object
{
}
class ObjectDemo
{
public static void main(String[]args)
{
Demo d1 = new Demo();
Demo d2 = new Demo();
System.out.println(d1.equals(d2)); //d1对象引用equals()方法去比较自己和对象d2是否为同一个对象。其实就是比较是否是同一地址。
}
}
程序结果:false
Object类中已经提供了对对象是否相同的比较方法equal (),如果自定义类中也有比较相同的功能,没有必要重新定义, 只要沿袭父类中的功能,建立自己特有比较内容即可,也就是覆盖。 Eg:
class Demo
{
private int num ;
Demo(int num)
{
this.num = num ;
}
public boolean equals(Object obj) //复写
{
if(!(obj instanceof Demo))
{
return false;
}
else
{
Demo d = (Demo) obj; //向下转换
return this.num == d.num;
}
}
}
class Person
{
}
class ObjectDemo
{
public static void main(String[]args)
{
Demo d1 = new Demo(4);
Demo d2 = new Demo (4);
Person p = new Person();
System.out.println(d1.equals(d2));
System.out.println(d1.equals(p));
}
}
程序结果:
true
false