您的位置:首页 > 职场人生

黑马程序员-面向对象03

2014-02-09 10:11 246 查看
----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------


1.继承 
    多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。多个类可以称为子类,单独这个类称为父类或者超类。
    子类可以直接访问父类中的非私有的属性和行为。
通过 extends 关键字让类与类之间产生继承关系。
 
1.1继承的优点
1.继承的出现提高了代码的复用性。
2.继承的出现让类与类之间产生了关系,提供了多态的前提。 
注意:千万不要为了获取其他类的功能,简化代码而继承。
必须是类与类之间有所属关系才可以继承。所属关系是 is a。
 
1.2继承的特点
父类:其实是由多个类不断向上抽取共性内容而来的。
java只支持单继承。java虽然不直接支持多继承,但是保留了这种多继承机制,进行改良(多实现)。
为什么不支持多继承呢?
    因为当一个类同时继承两个父类时,两个父类中有相同的功能,那么子类对象调用该功能时,运行哪一个呢?
    但是java支持多重继承。A继承B  B继承C  C继承D。
    多重继承的出现,就有了继承体系。体系中的顶层父类是通过不断向上抽取而来的。它里面定义的该体系最基本最共性内容的功能。
所以,一个体系要想被使用,直接查阅该系统中的父类的功能即可知道该体系的基本用法。那么想要使用一个体系时,需要建立对象。建议建立最子类对象,因为最子类不仅可以使用父类中的功能。还可以使用子类特有的一些功能。
简单说:对于一个继承体系的使用,查阅顶层父类中的内容,创建最底层子类的对象。
 
2.继承中子类父类中成员的特点
1:成员变量。
    |-- 子类有,就运行子类的变量,子类没有就运行父类的
    |-- 方法里有,不去外面找了 ,运行方法中的变量
    |-- 子类中,使用父类的成员变量,super.成员变量    
2:成员方法。
    |-- 子类父类出现了一模一样的方法的时候,子类重写(覆盖)父类的方法override
    |-- 保证子类方法的权限大于等于父类方法权限
    |-- 好处就在与可以提升程序的扩展性  手机案例,重复的直接使用super.方法()
什么时候使用覆盖呢?当一个类的功能内容需要修改时,可以通过覆盖来实现。
3:构造方法。
    |-- 子类构造(所有的)方法,必须访问父类的构造方法
    |-- 子类的构造方法的第一行隐式代码super(),默认访问父类的空参数的构造方法
    |-- 如果父类没有空参数的构造方法,子类的构造方法,没有手动写super 编译失败
    |-- 子类之间,可以通过this()语句的形式间接访问父类构造方法
|-- 子类中的方法一定多于父类中的方法吗
 
发现子类构造函数运行时,先运行了父类的构造函数。为什么呢?
原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super();
为什么子类对象初始化时,都需要调用父类中的函数?(为什么要在子类构造函数的第一行加入这个super()?)
因为子类继承父类,会继承到父类中的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。
 
注意:
如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。
 
问题:super()和this()是否可以同时出现的构造函数中。
两个语句只能有一个定义在第一行,所以只能出现其中一个。
 
super()或者this():为什么一定要定义在第一行?
因为super()或者this()都是调用构造函数,构造函数用于初始化,所以初始化的动作要先完成。
 
继承的细节:
什么时候使用继承呢?
当类与类之间存在着所属关系时,才具备了继承的前提。a是b中的一种。a继承b。狼是犬科中的一种。
英文书中,所属关系:" is a "
注意:不要仅仅为了获取其他类中的已有成员进行继承。
 
所以判断所属关系,可以简单看,如果继承后,被继承的类中的功能,都可以被该子类所具备,那么继承成立。如果不是,不可以继承。
在方法覆盖时,注意两点:
1:子类覆盖父类时,必须要保证,子类方法的权限必须大于等于父类方法权限可以实现继承。否则,编译失败。
2:覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)
 
继承的一个弊端:打破了封装性。对于一些类,或者类中功能,是需要被继承,或者复写的。
这时如何解决问题呢?介绍一个关键字,final:最终。
 
3.final
1:这个关键字是一个修饰符,可以修饰类,方法,变量。
2:被final修饰的类是一个最终类,不可以被继承。
3:被final修饰的方法是一个最终方法,不可以被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
5.内部类只能访问被final修饰的局部变量。
 
其实这样的原因的就是给一些固定的数据起个阅读性较强的名称。
不加final修饰不是也可以使用吗?那么这个值是一个变量,是可以更改的。加了final,程序更为严谨。常量名称定义时,有规范,所有字母都大写,如果由多个单词组成,中间用 _ 连接。
 
4.抽象类:abstract
概念:抽象就是从多个事物中将共性的,本质的内容抽取出来。
例如:狼和狗共性都是犬科,犬科就是抽象出来的概念。
 
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
抽象方法的由来:
多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可是吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是并不明确吼叫的细节。
 
4.1抽象类的特点
  |-- 被abstract修饰的方法,称为抽象方法,不能有方法体,不要写大括号
  |-- 抽象方法,必须存在于抽象类中,类也需要abstract修饰
  |-- 不可以实例化,不能建立对象 不可以 new 
抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例。例如:犬科是一个抽象的概念,真正存在的是狼和狗。而且抽象类即使创建了对象,调用抽象方法也没有意义。
  |-- 抽象类通过其子类实例化,定义子类,继承抽象类,覆盖所有抽象方法,建立子类对象。如果子类覆盖了部分抽象方法,这个子类还是抽象类
  |-- 抽象类,可以存在普通方法的,也可以没有抽象方法这样做仅仅是不让该类建立对象。
  |-- 抽象类,有构造方法的,可以为子类赋值操作,参考程序员和经理的案例*****
抽象关键字abstract不可以和哪些关键字共存?
final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。
       而抽象方法出现的就是需要被复写。
static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。
      可是抽象方法运行没意义。
 
练习:Abstract
/*
假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个
奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方
法进行属性访问。

员工类:name id pay

经理类:继承了员工,并有自己特有的bonus。

*/

abstract class Emplyee
{
private String name;
private String id;
private Double pay;

Emplyee(Stringname,String id,Double pay)
{
this.name= name;
this.id= id;
this.pay= pay;
}

public abstract void work();
}

class Manager extends Emplyee
{
private int bouns;
Manager(Stringname,String id,Double pay,int bonus)
{
super(name,id,pay);
this.bouns= bouns;
}

public void work()
{
System.out.println("Managerwork");
}
}

class Pro extends Emplyee
{
Pro(Stringname,String id,Double pay)
{
super(name,id,pay);
}

public void work()
{
System.out.println("Prowork");
}
}

class AbstractDemo
{
public static void main(String[] args)
{
Managerm = new Manager("张三","001",12000.00,5000);
m.work();
Prop1 = new Pro("李四","022",8000.00);
p1.work();

}
}


4.2模板方法设计模式:
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去。由该类的子类去完成。
 
练习:获取一段程序运行的时间 Abstract+Final的应用
/*
需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减即可。

获取时间:System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题。

这种方式,模版方法设计模式。

*/

abstract class GetTime
{
public final void getTime() //final修饰下,不让其他子类复写
{
long start = System.currentTimeMillis();
run Code();  //不确定的功能部分,提取出来,通过抽象方法实现
long end = System.currentTimeMillis();

System.out.println("耗时:"+(end-start));
}
public abstract void runCode();  //抽象不确定的功能,让子类复写实现
}

class RunCode extends GetTime
{
public void runCode()
{
for(int x=0; x<4000; x++)
{
System.out.print(x);
}
}
}

class GetTimeDemo
{
public static void main(String[] args)
{
Run Codegt = new RunCode();
gt.getTime();
}
}


接口
接口就是对外暴露的规则;是程序的功能扩展
初期理解,可以认为是一个特殊的抽象类
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
定义接口:interface 接口名
接口中的成员修饰符是固定的。
    成员常量:public static final int X = 20;
成员函数:public abstract void show();
接口中权限必须是 最大的public
接口的出现将“多继承”通过另一种形式体现出来,即“多实现”
5.1接口特点
  |-- 成员都是由固定格式,修饰符写不写也有!!
  |-- 权限必须是public 最大权限
  |-- 接口中的方法全部都是抽象的
  |-- 子类(实现类) implements接口,并覆盖接口中全部的抽象方法,建立子类的对象
         接口可以被多实现。一个子类,在继承一个类的同时,可以实现多个接口
     如;class ABImpl extends C implements A,B
         如果A,B这两个接口,有一样的抽象方法,没有主体。子类覆盖说了算
5.2接口的使用
     1. 接口不能建立对象 new 接口
 2. 定义子类 实现接口,并覆盖接口中的全部抽象方法,建立子类的对象
class 子类 implements 接口{
  覆盖抽象方法
}
 3. 如果子类只覆盖了部分抽象方法,子类还是一个抽象类
 4. 子类看做是这个接口的实现类,先期理解为继承,接口看做是子类的父类
5.3 java中支持多继承吗
  类与类之间是继承关系 extends
  类和接口之间是实现关系 implements
  接口与接口之间是继承关系 extends
  接口之间支持多继承,一个接口同时继承多个接口
 
  问java中支持多继承吗?
  类与类之间不支持,接口之间支持多继承
 
5.4继承extends和实现implements的区别
    1. 继承的单继承
2. 可以多实现
3. 继承后,父类的方法可以被子类直接使用
4. 实现后,必须覆盖抽象方法,才可以使用子类
5. 多实现的出现,避免了单继承的局限性
 
5.5抽象类abstrct class和接口interface的区别
   1. 抽象类可以有非抽象的方法(普通方法);接口全部都是抽象方法
   2. 接口中的成员都是固定的  final
   3. 抽象类的成员修饰符可以自定义。
      接口中的成员修饰符是固定的。全都是public的。 
   4. 抽象类被子类继承可以直接使用非抽象方法
      接口必须实现后覆盖全部的抽象方法
   5. 抽象类是这个继承体系的最共性内容 子类是之间是一个 is a关系
      接口是这个体系外的扩展功能,实现类之间是一个 like a关系
 
   猫继承自哺乳动物
   基础班是传智播客的一个班级,看起来也像一个烟民。
 
5.6接口的好处
接口就是对外暴露的规则;是程序的功能扩展
1.接口的出现降低耦合性 
2.接口可以用来多实现。避免了单继承的局限
6.多态
就是父类或者接口的引用指向自己的子类对象  //Animal a = new Cat();
目的:是为了扩展程序,无限的增加子类,只要子类重写了方法
              Fu f = new Zi();  f.方法(); 子类重写
好处:提高了程序的扩展性
弊端:只能调用子类重写的方法,不能调用子类特有的方法
    如果想用子类对象的特有方法,先通过instanceof判断对象是哪个具体的子类类型,再强制向下转型  
    关键字 instanceof //判断对象是否实现了指定的接口或继承了指定的类
前提: 必须要有关系,比如继承、或者实现。
  通常会有覆盖操作。
多态的出现思想上也做着变化:
以前是创建对象并指挥对象做事情。有了多态以后,我们可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,即通过操作父类或接口实现。
 
多态中成员特点:
非静态成员方法 编译看左边,运行看右边
其他的编译和运行全看左边
 
 
/*
需求:
电脑运行实例,
电脑运行基于主板。
*/

interface PCI
{
public void open();
public void close();
}

class MainBoard
{
public void run()
{
System.out.println("mainboardrun ");
}
public void usePCI(PCI p)//PCI p = new NetCard()//接口型引用指向自己的子类对象。
{
if(p!=null)
{
p.open();
p.close();

}
}
}

class NetCard implements PCI
{
public void open()
{
System.out.println("netcardopen");
}
public void close()
{
System.out.println("netcardclose");
method();
}

}
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCardopen");
}
public void close()
{
System.out.println("SoundCardclose");
}
}

class DuoTaiDemo
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(newNetCard());
mb.usePCI(newSoundCard());

}
}

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: