黑马程序员——Java基础——面对对象

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

面向对象

一、面对对象的特点 :

1.将复杂的事情简单化

2.面性对象将以前的过程中的执行者变成了指挥者。

3.面向对象这种思想是符合现在人们思考习惯的一种思想

过程和对象在我们程序中是如何体现的呢?

过程就是函数,对象时将函数等一些内容进行了封装。


对象、类有什么区别?

类是对象的抽象,对象是类的具体表现形式,类就是一类事物,而对象就是一个事物,一类事物中包含若干的事物(而这其中的具体的事物就是对象)。

比如:类就是车的模型,对象就是具体的车,车可能有红色,可能有蓝色,对象之间是有差异的。

面向对象和面向过程有什么区别?

面向过程强调执行的动作和执行的过程,而面向对象强调结果。

类就是:对现实生活中事物的描述。
对象:就是这类事物,实实在在存在个体

注:

在Java的开发过程,其实就是不断的创建对象,使用对象,指挥对象做事情。设计的过程,其实就是在管理和维护对象之间的关系。


二、面向对象的三个特性:

1.封装

1.1 基本概念 

封装(encapsulation)是面向对象三大特征之一,它是指将对象的状态信心隐藏在对象的内部,不允许外部直接进行访问,而是通过该类提供的方法来实现对内部信息的操作和访问。封装的作用如下:

a)、隐藏类的实现细节。

b)、让使用者只能通过实现预定的方法来访问数据,从而可以在方法里添加逻辑控制,限制对类成员的不合理访问

c)、可以进行检查,从而有利于保证对象信息的完整性。

d)、便于修改,提高代码的可维护性

1.2 具体实现规律

为了实现良好的封装,需要从以下两个方面进行考虑:

a)、将队形的成员变量和实现细节进行隐藏,不允许外部进行直接访问。

b)、把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。


因此封装实际上有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。这两个方面都需要通过java的访问控制符去实现。


下面程序便演示了封装的表现形式:


 class Person{

        private String name;

        private int age;

        public String getName() {

            return name;

        }

        public void setName(String name) {

            this.name = name;

        }

        public int getAge() {

            return age;

        }

        public void setAge(int age) {

            this.age = age;

        }

   }

2.继承

继承是面向对象的三大特征之一,也是实现软件复用的重要手段。Java的继承只允许单继承,但是运行多实现。

2.1 继承特点:

a)、提高了代码的复用性

b)、让类与类之间产生了关系,有了这个关系,才有了多态的特性。必须是类与类之间有所属关系才可以使用继承。

2.2 继承体系的使用规律:

查阅父类的功能,建立子类的实例。

2.3 原因:

因为有可能父类不能创建对象

创建子类对象可以使用更多功能,包括基本的也包括特有的。

2.4 子父类中变量特点

父类的成员变量私有化之后,子类依然继承,但不能直接访问。
如果子类中出现非私有的同名成员变量时,自类要访问本类中的变量用 this ,要访问父类中的同名变量,用super

2.5 覆盖

当子类中出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。这就是重写。
当子类继承了父类,沿袭了父类的功能,到子类中,但是子类虽然具备该功能,但是功能的内容却和父类不一样,这是没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。这是用 super。
注意:
子类覆盖父类,必须保证子类权限大于等于父类权限,才能重写
静态只能访问静态

2.6 子父类中构造函数特点

在对子类对象进行初始化时,父类的构造函数也会运行。子类只会隐式调用父类的空参构造函数

2.7 子类一定会访问父类中的构造函数原因:

因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

2.8 其他

子类的所有构造函数,默认都会访问父类中无参的构造函数,因为子类的每一个构造函数内的第一行都有一句隐式super();

当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。

当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。

//定义一个人父类
class Person
{
	//名字和年龄是人的共有属性
	String name;
	int age;
	
	//在构造函数中对名字和年龄进行初始化
	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
		System.out.println(name+"  "+age);
	}
	//人都具有睡觉的功能
	void sleep()
	{
		System.out.println("sleep");
	}
}
//定义一个学生,继承人,作为子类
class Student extends Person
{
	Student(String name,int age)
	{
		super(name,age);	//super关键字表示父类,因为姓名和年龄在父类中进行了初始化动作,在这里可以直接调用
	}
	//学生具有特有的功能,学习
	void study()
	{
		System.out.println("study");
	}

}

class Demo
{
	public static void main(String[] args)
	{
		Student s=new Student("zhangsan",20);
		System.out.println(s.name="wangwu");
		s.sleep();
		s.study();
	}
}



3.多态

Java引用变量有两种类型,一个是编译时类型,一个是运行时类型。编译时类型有声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态(polymorphism)。

3.1 多态的理解

可以理解为事物存在的多种体现形态。表现为父类的引用指向子类的对象。

3.2 多态的体现

父类的引用指向子类的对象,父类的引用接收子类的对象。

3.3多态的前提

类与类之间必须是继承或者实现的关系。通常还有一个前提 就是覆盖

3.4 多态的好处

大大的提高了程序的扩展性

3.5 多态的弊端

提高了扩展性,但是只能使用父类的引用访问父类中的成员。

3.6 多态的应用

定义好工具类,即将共同行为封装在一个类中。

        对类型进行抽取,---->多态的产生。

        操作同一父类型,对其中的子类型均可操作


3.7 多态中成员的特点

a)、多态中非静态成员函数的特点

        在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。

如:在上面的示例中,如果用a.catchMouse();编译就会报错。这时只能通过强转,向下转型后,可以使用子类的特有功能。

        在运行时期:参阅对象所属的类中是否有调用的方法。这就是说,如果父类中有一个非抽象的方法,而子类继承后又将其复写了,在多态运行时,父类的引用调用这个同名函数时,被运行的将是父类中的方法。

        简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

b)、多态中成员变量的特点

        无论编译和运行,都参考左边(引用变量所属的类)。如:多态中的父类引用调用成员变量时,如果父类和子类有同名的成员变量,那么被调用的是父类中的成员变量。

c)、多态中静态成员函数的特点

        无论编译和运行,都参考左边。也就是父类引用在调用静态同名函数时,被调用的是父类中的静态函数。这是因为,当类一被加载,静态函数就随类绑定在了内存中。此时,不需要创建对象,就可以使用类名直接调用。同时,父类中的静态成员函数一般是不被复写的。

类在方法区中的分配:分为静态区和非静态区,而关键字this和super在非静态区。

3.8 如何使用子类特有方法

Animal a=new Cat();//类型提升,向上转型。

a.eat();//父类的共有方法。

如果要调用cat的特有方法的时候 ,就必须将父类的引用转成子类的类型,但是不能将父类对象转成子类类型,转换的是父类的引用,(就是父类的变量)

  Cat c=(Cat)a;

c.catchmouse();//子类的特有方法。

//父类————动物
abstract class Animal
{
	public abstract void eat();

}

//子类————猫
class Cat extends Animal
{
	//复写父类中的抽象功能
	public void eat()
	{
		System.out.println("吃鱼");
	}

	//Cat特有的功能
	public static void catchMouse()
	{
		System.out.println("抓老鼠");
	}
}


class Demo
{
	public static void main(String[] args) 
	{
		Animal a = new Cat();
		a.eat();
		Cat c = (Cat)a;
		c.catchMouse();
	}
}



二、抽象类(abstract)    

当编写一个类时,时常会为该类定义一些方法,这些方法的使用用以描述该类的行为方式,那么这些方法都有具体的方法体。但是在某些情况下,某个父类只是知道子类应该包含怎样的方法,但是无法精确的知道这些子类是如何实现这些方法,例如定义一个GetTime类,该类提供了一个计算某一段程序运行时间的gettime方法,但是无法知道具体运行什么方法体,这时就需要使用抽象方法来实现了。

抽象类概念

当多个类中出现相同功能,但是功能主体不同,这时候可以进行向上抽取,只抽取功能定义,而不抽取功能主体。分析事物不确定时,就抽象。

1.特点:

     1.抽象方法只能定义在抽象类中。

     2.抽象方法和抽象类必须被abstract修饰

     3.抽象类不可以用new 创建对象,因为创建对象没有意义

     4.抽象类中的抽象方法要被使用,必须由子类复写抽象方法后,建立子类对象调用

     5.如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。如果不想子类是抽象类必须,复写父类抽象类中的全部抽象方法。

特殊

抽象类中可以不定义抽象方法,这样做仅仅是为了避免建立本类对象

2.什么时候使用抽象:

抽象类和一般类没有太大的区别,当事物出现不确定的功能,需要明确指出,但是无法定义主体,通过抽象方法来表示

抽象类比一般类多了个抽象方法抽象类不可以实例化,抽象类中还可以定义非抽象方法,目的是不让该类建立对象

3.抽象类成员

抽象类可以包含 普通方法、 成员变量、 构造方法

4.抽象格式特点

在需要抽象的方法上用abstract进行修饰,同时该方法没有方法体,结尾';'结尾。

5.应用:


假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个
奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方
法进行属性访问。

员工类:name id pay

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

*/

//员工类,也是父类
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 int bonus;//特有的奖金属性
	Manager(String name,String id,double pay,int 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  AbstractDemo 
{
	public static void main(String[] args) 
	{
		new Manager("manager","001",10000,2000).work();
		new Pro("pro","020",5000).work();
	}
}



注意事项:

     不能与 final 一起使用:抽象是用来继承的所以不可以与final同时使用。

     不能与private一起使用: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。而抽象方法出现的就是需要被复写。

     不能与 static 一起使用:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。可是抽象方法运行没意义。

     抽象类该怎样描述事物就怎么描述,只是有一些内容"看不懂",所以可以有包含成员变量与方法,构造方法。

     如果一个类中存在抽象方法,那么该类一定要用abstract修饰(该类一点是抽象类)

三、接口(interface)

     由于电脑买的比较早,硬盘的容量很小,随着时间的推移慢慢的感觉到存储容量的压力,但是电脑为我提供了一个USB接口,由于USB接口的存在,我买一个移动硬盘就很好的解决了硬盘容量不足的问题,假设如果没有USB接口要想解决这个问题就需要更换硬盘,或者换电脑其弊端大家很容易就明白了。这里我们说的接口和要介绍的程序接口道理是相通的。

1.接口概念

     接口定义了一系列规范,想要实现某一个功能就必须遵守该规范,也就是说是 要想实现某一个接口,就must be按照使用接口的规范(读者反馈,谢谢)

     初期理解,可以认为是一个特殊的抽象类当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。

2.特点

1,接口中可以定义:常量,抽象方法。

2,接口中的成员都有固定修饰符:

           常量:public static final

           方法:public abstract

记住:接口中的成员都是public的。

3,接口不可以创建对象

3.接口作用

1,接口是对外暴露的规则

2,接口是程序的功能扩展

3,接口的作用主要是为了统一访问

4.什么时候使用接口

当使用一个函数(暂且说是函数吧)时,但是函数的主体不确定,只是定义该方法的规范比如返回值,参数列表时,这是就应该考虑使用接口区定义。

5.接口的成员

常量,抽象方法。

6.接口格式特点

在生命一个类是接口时不再吃用class 而是使用 interface去定义。

7.注意事项

接口:是不可以创建对象的,因为有抽象方法。

需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。

接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。

接口之间关系为继承,需要特别声明的是接口之间允许使用多继承所以从这个角度来说 java支持多继承

8.应用实例

   

//抽象学生类
abstract class Student
{	
	//抽象的学习方法
	abstract void study();
	//共性内容非抽象的睡觉方法
	void sleep()
	{
		System.out.println("sleep");
	}
}

//接口,吸烟
interface Smoking
{
	void smoke();
}

//Zhangsan这个对象继承学生类,实现吸烟接口
class Zhangsan extends Student implements Smoking
{
	//复写学习方法
	void study()
	{
		System.out.println("Zhangsan_study");
	}

	//复写吸烟方法
	public void smoke()
	{
		System.out.println("Zhangsan_smoking");
	}
}

//Lisi是好学生,不吸烟
class Lisi extends Student 
{	
	//复写学习方法
	void study()
	{
		System.out.println("Lisi_study");
	}
}


class InterfaceDemo
{
	public static void main(String[] args) 
	{
		Zhangsan z = new Zhangsan();
		z.study();
		z.smoke();
		new Lisi().study();
	}
}




抽象与接口区别

    抽象:

         1、抽象类是可以有私有方法或私有变量的,实现抽象类可以有选择地重写需要用到的方法,

            但是必须实现里面所有的抽象方法。

         2、抽象类在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。

         3、抽象类中可以有自己的数据成员,也可以有非abstarct的成员方法。

         4、抽象类和接口所反映出的设计理念不同。其实abstract class表示的是"is-a"关系

         5、抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

    接口:

         1、接口是公开(public)的,里面不能有私有的方法或变量,是用于让别人使用的,

            实现接口的一定要实现接口里定义的所有方法。

         2、一个类却可以实现多个interface(java中实现多重继承的方法之一)。

             而在接口中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,

         3、不过在 interface中一般不定义数据成员),而且所有的成员方法都是抽象的。

         4、interface表示的是"like-a"关系。(组合是"has a"关系)

         5、接口中定义的变量默认是public static final 型,且必须给其初值,

            所以实现类中不能重新定义,也不能改变其值。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值