程序员_Java基础<三>-面向对象下

 

涉及的内容:多态、抽象类、接口、设计模式之模板方法

<一、多态>

多态:可以理解为事物存在的多种体现形态。在对象上的体现。
1.多态的体现:父类的引用指向了自己的子类对象。
     父类的引用也可接受子类的对象。如 Animal c=new Cat()
2.多态的前提:
必须是类与类之间有关系,要么继承,要么实现。
通常还有一个前提:存在覆盖。
3.多态的好处:
多态大大提高了程序的扩展性。
4.多使态的弊端:
调高了扩展性,但是只能使用父类的引用访问父类中的成员。不能访问子类特有的成员,
例如不能访问猫吃鱼的方法。
5. 多态的应用:
6. 多态的出现代码 中的特点(多态使用的注意事项)
*/

abstract class Animal
{
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 DuoTai
{
public static void main(String[] args)
{
function(new Cat());//相当于Animal a=new Cat();
function(new Dog());
}
public static void function(Animal a)
{
a.eat();
}
}


/*多态--转型*/
接上面:主函数变成:
public static void main(String[] args)
{
Animal a==new Cat();//类型提升。向上转型,将Cat对象赋给Animal的引用。
a.cat();
//如果想要调用猫的特有方法时,该怎么操作?
//强制将父类的引用,转成子类类型,向下转型。
Cat c=(Cat)a;
c.catchMouse();
//另外注意:千万不要下面这样做,就是将父类对象转成子类类型。
//我们能转换的是父类应用指向了自己的子类对象时,该引用可以被提升,也可以被引用强制转换。
//多态其实自始至终都是子类对象在做着变化。(重要!都是子类的功能内容)
Animal a=new Animal();
Cat c=(Cat)a;
}


/*多态其实自始至终都是子类对象在做着变化*/
形象解释上句话:
父亲 x=new儿子();//儿子化妆成父亲,其实还是儿子
x.讲课();//表面是父亲讲课,实际却是儿子讲课的内容
儿子  y=(儿子)x;//儿子卸妆,又转型回儿子
y.看电影();//儿子调用儿子特有的方法。
/*判断所属类型-instanceof*/
class DuoTai
{
public static void main(String[] args)
{
function(new Cat());
function(new Dog());
}
public static void function(Animal a)
{
a.eat();
if(a instanceof Cat)
{
Cat c=(Cat)a;
c.catchMouse();
}
else (a instanceof Dog)
{
Dog c=(Dog)a;
c.kanJia();
}
}
}


/*多态示例*/
/*
基础班学生:学习,睡觉。
高级版学生:学习,睡觉。
可以将这两类事物进行抽取。
*/
abstract class Student
{
public abstract void study();
public void sleep()
{
System.out.println("躺着睡")
}
}
class BaseStudent extends Student
{
public void study()
{
System.out.println("base study");
}
public void sleep()
{
System.out.println("坐着睡")
}
}
class AdvStudent extends Student
{
public void study()
{
System.out.println("adv study");
}

}
class DoStudent
{
public void dosome(Student stu)
{
stu.study();
stu.sleep();
}
}
class DuoTaiDemo
{
public static void  main(String[] args)
{
DoStudent ds=new DoStudent();
ds.dosome(new BaseStudent());
ds.dosome(new AdvStudent());
}
/*BaseStudent bs=new BaseStudent();
bs.study();
bs.sleep();
AdvStudent as=new AdvStudent();
as.study();
as.sleep();*/

}


/*
1.在多态中成员函数(非静态)的特点:
在编译时期:参阅引用型变量所属的类中是否有要调用的方法,如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结:成员函数在多态调用时,编译看左边,运行看右边。

2.在多态中,成员变量的特点:
无论编译还是运行,都参考引用型变量所在类中的变量值。
3.在多态中,静态static成员函数特点;
无论编译还是运行,都参考引用型变量所在类的成员函数即左边。。
*/
class Fu
{
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()
{
System.out.println("fu method_4");
}
}
class Zi extends Fu
{
void method1()
{
System.out.println("zi method_1");
}
void method3()
{
System.out.println("fu method_3");
}
static void method4()
{
System.out.println("zi method_4");
}
}
class DuoTaiDemo4
{
public static void main(String[] args)
{
Fu f=new Zi();
f.method1();//结果是zi method_1,因为父类中method1被覆盖。
f.method2();//fu method_2,因为子类继承了父类的method2方法。
//f.method3();//编译失败,父类引用不能调用子类特有方法,
//因为此时子类对象在编译时并没有创建,编译时检查左边引用类型所在类所拥有的方法中没有method3方法.报错.
/*注意*/ f.method4();//结果fu method_4,因为static函数在类加载时就已经存在
//而不需要对象,即不参考右边的子类对象,和子类没关系。
}
}



问题在多态中,实际存在着变量的覆盖关系吗?
解答:因为子类其实是一种特殊的父类,因为Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换,或者被称为向上转型,向上转型是由系统自动完成的。Java引用变量有两个类型,一个是编译时的类型,一个是运行时的类型。
编译时的类型是由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
如果编译时类型和运行时类型不一致,就会出现所谓的多态。
通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时类所定义的属性。
记住一点:多态中只有方法可以重写,变量不存在重写.


/*多态不但在继承中使用,在接口实现中也可以*/
class MainBoard
{
public void usePCI(PCI p)//PCI p=new netCard()//接口引用指向自己的子类对象
{
if(p!=null)
{
p.open();
p.close();
}
}
}
class NetCart implements PCI


{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
MainBoard mb=new MainBoard();
mb.usePCI(new NetCard());
}
}


/*

<二、抽象类>

抽象类:abstract
    当多个类中出现了相同功能,但是功能主体不同,这时可以进行向上抽取,(抽象abstract只可以修饰类和方法)
    这时只抽取功能定义,而不抽取功能主体。注意抽象方法的特征是描述不到具体的事物。
抽象类的特点:
1.abstract方法只能存在于abstract类中。
 2. 抽象类不可以用new创建对象,因为调用抽象方法无意义 。
3.抽象类中的方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法了,那么该子类必须是一个抽象类(因为当子类没有复写父类全部的抽象类时,相当于继承了父类剩余的抽象方法,而抽象方法必须存在于抽象类中,所以该子类也必须是抽象类)
 4.抽象类和一般类没有多大的不同。在里面既可以定义非抽象方法也可以定义抽象方法。
5抽象类比一般类多了抽象函数,抽象类不可以实例化。
 注意:抽象类中可以不定义抽象方法,这样做仅仅是为了不让该类建立对象。
*/
实例代码:

abstract class Student
{
    abstract void study();
}
class BaseStudent extends Student
{
void study()
{
System.out.println("base student");
}
}
class AdvStudent extends Student


{
void student()
{
System.out.println("adv study");
}
}
class AbstractDemo
{
public static void main(String[] args) 
{
new BaseStudent().study;
}
}


/*
抽象类练习:
假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性:姓名,工号,以及工资。
经理也是员工,除了含有员工的属性外,另外还有一个奖金属性。请使用继承的思想设计出
员工类和经理类。要求类中提供必要的方法进行属性访问。
*/
abstract class Employee//员工
{
private String name;
private String id;
private double pay;
Employee(String name,String id,double pay)
{
this.name=name;
this.id=id;
this.pay=pay;
}
public abstract void work();
}


class Manager extends Employee//经理
{
private double bonus;
Manager(String name,String id,double pay,double bonus)
{ 
super(name,id,pay);
this.bonus=bonus;
}
public void work()
{
System.out.println("manager work");
}
}
class Pro extends Employee//普通员工
{
Pro(String name,String id,double pay)
{
super(name,id,pay);
}
public void work()
{
System.out.println("pro work");
}
}
class  EmployeeDemo
{
public static void main(String[] args) 
{
Pro pro=new Pro(li,li,9999);
pro.work();
Manager man=new Manager(li,li,1999,333.3);
man.work();
}
}


<三、接口>


一,接口:初期理解,可以认为是一个特殊的抽象类。
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式表示。
class用于定义类。
interface用于定义接口。
二.接口定义时,格式特点:
1.接口中常见定义:常量,抽象方法。
2.接口中的成员都有固定修饰符。
常量:public static final
方法:public abstract
记住:接口中的成员都是public的,上述修饰符,当你没写时,因为有interface关键字,所以系统会自动加上,但是为了阅读,最好加上.
三.接口:是不可以创建对象的,因为有抽象方法需要被子类实现,子类对接口中的抽象方法全部都覆盖后,子类才可以实例化。否则子类是一个抽象类。
接口的多实现:接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。
四.注解:为什么java不支持多继承而支持多实现呢?
不支持多继承:父类中方法可能有重复,导致子类调用时,不知道调用哪个,出现问题.
支持多实现:因为接口中没有方法主体,可以由子类任意定义.
注意:接口之间支持多继承
五.接口与接口关系:继承关系
类与接口:实现
类与类:继承
六:接口的特点总结:
1.接口是对外暴露的规则。
2.接口是程序的功能扩展。
3.接口可以用来多实现。
4.类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
5.接口与接口之间可以有多继承关系。

interface Inter
{
public static final int NUM=3;
public abstract void show();
}
interface InterA
{
public abstract void methodA();
}
interface InterB
{
public abstract void methodB();
}
interface InterC extends A,B//注意:接口之间支持多继承
{
public abstract void method();
}


class Test implements Inter, InterA//
{
public void show(){};
public void method(){};
}
class InterfaceDemo


{
public static void main (String[] args)
{
Test t=new Test();
Syetem.out.println(t.NUM);
Syetem.out.println(Test.NUM);
Syetem.out.println(Inter.NUM);
}
}



/*接口举例体现*/
abstract class Student//基本功能定义在类中,用来继承


{


abstract void study();
void sleep()
{
System.out.println("sleep");
}
}
interface Smoking//特殊功能定义在接口中,用来扩展
{
void smoke();
}
class ZhangSan extends Student implements Smoking
{
void study(){}
public void smoke(){}
}
class  
{
public static void main(String[] args) 
{
System.out.println("Hello World!");
}
}


<四、设计模式:模板方法>

模板方法模式:
需求:获取一段时间程序运行的时间。
原理:获取程序开始和结束的时间并相减。
获取时间:System.currentTimeMillis();
当代码完成后,就可以解决这类问题了。
这种方式为,模板方法设计模式。
什么是模板方法呢?
在定义功能时,功能的一部分是确定的(如 父类的getTime方法),但是有一部分是不确定的,
而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,有该类的子类去完成(覆盖)


*/

abstract class GetTime
{
public final void getTime()//为了保证该方法不被覆盖。
{
long start=System.out.currentTimeMillis();

runcode();
long end=System.out.currentTimeMillis();
System.out.println("毫秒"+(end-start));
}
public abstract void runcode();//因为功能不确定,所以可以定义为抽象方法,由子类去覆盖
}
class SubTime extends GetTime


{
public void runcode()
{
for(int x<o;x<1000;x++)
{
System.out.println(x);
}
}
}


/*



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值