面向对象特征
封装
封装概念:
- 封装,将类的某些信息隐藏在类内部,不允许外部访问,而且时通过该类提供的方法来实现对隐藏信息的操作和访问
优点:
- 隐藏类的实现细节
- 类内部的结构可以自由的修改
- 可以对成员精确的控制
- 只能通过规定方法访问
- 良好的封装能够减少耦合
具体表现
- 属性使用private权限
- 方法使用public权限
public class Person {
private String name;
private int age;
}
将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏
其构造方法,及Setter,Gestter方法.即每个值属性提供对外的公共方法访问,也就是创建一堆赋值的方法,用于访问私有属性的访问,例如:
public class EncapTest{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
this 关键字是为了解决实例变量(private String name)和局部变(setName(String name)中的name变量)之间发生的同名的冲突。
测试:
public class RunEncap{
public static void main(String args[]){
EncapTest encap = new EncapTest();
encap.setName("James");
encap.setAge(20);
encap.setIdNum("12343ms");
System.out.print("Name : " + encap.getName()+
" Age : "+ encap.getAge());
}
}
this关键字
this关键字代表自身类的对象
- 使用this关键字引用成员变量
- 使用this关键字引用成员方法
注意:this关键字必须放在非静态方法里面
使用“this.成员变量名”这样的格式来引用成员变量名,,常常硬来区分同名的成员变量呵和局部变量
继承
继承是面向对象程序设计思想,是实现代码可重用的根基,是提高代码可扩展性的主要途径。
- 继承是从已有的类中派生出新的类,新类能吸收已有类的属性和行为,并能扩展新的能力
- Java中使用extends关键字来表示继承关系
- java不支持多继承,一个子类只有一个父类
- 继承后子类可以调用父类的所有非私有属性和非私有方法
使用继承
- 符合is-a关系的设计,使用继承
- 将子类共有的属性和行为放到父类中
例如: 猫是动物, (子类)猫类的(父类)就是动物类
继承是代码重用的一种方式
继承形式
[访问权限修饰符][修饰符] 子类名 extends 父类名{子类体}
父类(动物类)
public class Animal {
public void eat() {
System.out.println("动物吃");
}
}
子类(猫类)
public class Cat extends Animal {
public void play() {
System.out.println("猫在玩耍");
}
}
测试
public class Test {
public static void main(String[] args) {
Cat cat=new Cat();
cat.play();//子类属性
cat.eat();//父类属性
}
}
专业术语
cat类是 Animal类的子类, Animal类是cat类的父类
cat类是 Animal类的派生类, Animal类是cat类的基类
继承传递性
- 继承后子类可以调用父类的所有非私有属性和非私有方法,并别可以多层传递,C类从B类继承,B类又从A类继承那么C类就具有B类和A类的所有非私有属性和非私有方法
- 当一个类没有继承任何一个类时,jvm会默认让继承Object类…Object是java为所有类提供的基类
super关键字
super关键字代表父类的引用,在程序中主要途径
- 在子类构造中调用父类的构造方法,super语句只能出现子类构造方法体的第一行
- 用"super.成员变量名"用来引用父类成员变量
- 用"super.方法名(参数列表)"的方式访问父类的方法.
- 与this的区别,this通常指代当前对象,super通常指代父类.
方法的重写
重写overRide 重载overload
子类方法根据父类中继承的方法进行重写
方法重写规则:
- 方法名相同,参数相同
- 返回值类型相同
- 访问权限相同
-即于父类方法结构完全相同
注意:构造方法不能重写
应用场景:当此父类的方法不能满足子类需求时,可以对方法进行重写(overRide)
package com.nie.day5.demo01;
public class Animal1 {
private String a;
private String eat;
public Animal1() {
super();
System.out.println("Animal无参构造");
}
public Animal1(String a) {
this.a = a;
System.out.println("Animal有参构造");
}
public void eat() {
System.out.println("动物吃");
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getEat() {
return eat;
}
public void setEat(String eat) {
this.eat = eat;
}
}
package com.nie.day5.demo01;
import com.nie.day4.demo1.demo02.Animal;
public class dog extends Animal1 {
/**
* 子类构造方法,先调用父类的构造方法,默认情况下调用父类的无参构造方法
* super 调用父类任意一个构造方法
*/
public dog() {
super(); //- 用"super.成员变量名"用来引用父类成员变量
//- 用"super.方法名(参数列表)"的方式访问父类的方法.
//super("d");//super语句只能出现子类构造方法体的第一行
System.out.println("dog无参构造");
}
/**
* 重写override 重载 overload
* 方法名,参数列表相同
* 返回值类型相同
* 访问权限相同, 即父类的方法结构完全相同
* 注意:: 构造方法不能重写
*
* 场景: 父类的方法不能满足子类的时,需要对方法进行重写
*
*
*/
@Override//表示此方法有父类重写而来
public void eat(){
System.out.println("狗吃");
super.eat();
}
}
测试
public class Test {
public static void main(String[] args) {
dog a = new dog();
a.eat();
}
}
Animal有参构造
dog无参构造
狗吃
动物吃
类之间关系–关联,依赖
关联
has-a
- 对象与对象之间的连接,.在Java中,关联关系的代码表现形式为一个类做为另外一个类的属性类型存在…类与类之间的一种最常用的关系。
- 即“有”的关系:”has-a”。
关联关系为:关联关系的多重性
- 单向关联,自关联 一对一关联:一个学生,只能在一个班级里学习。
- 双向关联:可以调用对对方的公共属性和方法,例如知道对方的存在供货商和顾客
双向关联
publc class Customer{
//供货商对象数组作为顾客的属性成员
private Supplier [] supplier;
}
public class Supplier {
public Customer [] customer;
}
单向关联
publc class Customer{
private Address address;
}
public class Address {
}
自关联
public class Customer{
private Customer customer;
}
依赖
use a 的关系为依赖关系
- 依赖关系(使用关系), 指一个类A使用到了另一个类B
- 依赖关系特性
这种关系是具有偶然性的,临时性的,非常弱的,但是类B的变化会影响到类A
课表与课程之间:
class CourseTable{
public void addCourse(Course c){
c.show();
System.out.println("新增课程");
}
pubilc void deCourse(Course c){
c.show();
System.out.println("删除课程");
}
}
class Course{
System.out.println("课程为:");
}
多态
同一事物,在不同时刻表现不同的状态
多态存在的必要的三个条件:
- 要有继承(前提条件)
- 要有重写(前提条件)
- 父类引用指向子类对象
- 当编译类型是父类,运行类型是子类时,被称为父类引用指向子类对象
- 多态环境下对成员方法的调用编译看左边,运行看右边。
- 多态环境下对静态成员方法的调用简单的说:编译和运行都看左边。
- 多态环境下对成员变量的调用编译和运行都看等号左边。注意:变量不出存在被子类覆写说法,只存在覆盖
方法的形参是父类类型,而传递的似乎实际参数可以是任意子类的对象
方法参数多态性的好处:提高代码的扩展性
父类(动物类)
package com.nie.day5.demo04;
/**
* 多态
* 同一种食物,在不同时刻表现不同的状态
*
* 多态存在的三个必须的条件
* --要有继承
* --要有重写
* --父类指向子类对象
*/
public class Animal {
int num=10;
public void eat() {
System.out.println("动物吃");
}
static void show(){
System.out.println("Animal");
}
public void fly(){
System.out.println("动物飞了");
}
}
子类(猫)
package com.nie.day5.demo04;
public class Cat extends Animal {
int num = 5;
public void eat() {
System.out.println("cat 吃");
}
static void show() {
System.out.println("静态成员方法");
}
void look(){
System.out.println("看家");
}
}
子类(狗)
package com.nie.day5.demo04;
/**
* * --要有继承
* * --要有重写
*/
public class Dog extends Animal{
public void eat() {
System.out.println("小狗一号 吃");
}
}
子类(狗1)
package com.nie.day5.demo04;
public class Dog1 extends Animal {
public void eat() {
System.out.println("小狗二号 吃");
}
}
测试
package com.nie.day5.demo04;
public class Test {
public static void main(String[] args) {
//父类指向子类对象
//父类 子类
Animal a = new Cat();
/**
* 多态环境下对成员方法的调用
* **编译看左边,运行看右边。**
*/
a.eat();
/**
* 多态环境下对静态成员方法的调用
* **简单的说:编译和运行都看左边。**
*/
a.show();
/**
* a.num 编译和运行都看等号左边
* 注意:变量不存在被子类覆盖写这一说法,只有方法存在覆盖
* 调用的是父类的成员变量
*/
System.out.println(a.num);
Animal b = new Dog();
b.eat();
Animal c = new Dog1();
c.eat();
Test t = new Test();
t.method(a);
}
//方法的形参是父类类型,而传递的是实际参数可以是任意子类的对象
//提高方法参数多态性的好处:提高代码的扩展性
public void method(Animal animal) {
animal.eat();
}
}
向上转型,向下转型
父类引用指向子类对象
- 向上转型的作用是:提高程序的扩展性。
- 向下转型的作用是:为了使用子类中特有的方法
public class Animal {
int num=10;
void eat() {
System.out.println("动物吃");
}
}
public class Cat extends Animal{
int num = 5;
void look(){
System.out.println("看家");
}
}
package com.nie.day5.demo05;
public class Test {//向下转型
public static void main(String[] args) {
Animal a = new Cat();//向上转型
//多态的问题:父类类型不能访问子类特有的方法
//解决办法: 向下转型
String s = "ads";
Object obj = s;
// 大类型 instanceof 小类型 判断检测大类型中是否包含的是具体的小类型
if (obj instanceof Cat) {
Cat m = (Cat) a;//向下转型
m.look();
} else {
System.out.println("不是");
}
}
}
final关键字
- final用于声明属性,方法和类
- 属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期不能修改
- 方法:子类不能被覆盖
- 类:不能被定义为抽象类或者接口,不可被继承.
final属性赋值:
–在声明时同时赋值,往往与static一起使用
final static int Num = 10;
package com.nie.day5.demo06;
public class Filal {
//用于声明方法和类
//final修饰常量,常量值不能变,利用static 修饰 节省空间
final static int Num = 10;
final int a = 100;
public final void eat() {
System.out.println("你好");
}
//定义就必须直接赋值或者在构造方法中进行中进行赋值,后期不能修改
public void num(int a) {
// this.a=1000;
System.out.println(a);
}
//在方法参数前加final关键字,防止数据在方法题中被修改.
public void num1(final int b) {
// b=11;
}
}
抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
抽象类除了不能实例化对象之外,类的其他功能依然存在,名成变量,成员方法和构造方法的访问方式和普通类一样.
用abstract修饰的类就是抽象类,如果某个类中包含抽象方法,那么这个类就必须定义抽象类.
抽象方法:
- 抽象方法时一种特殊的方法:他只有声明,而没有具体的实现
- 抽象方法必须用abstract关键字进行修饰
抽象类可以有成员属性和非抽象方法
抽象类不能被实例化,但可以有构造函数.因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象
抽象类不能创建对象:抽象类只能做基类,表示一种继承关系.
构造方法和静态方法不可以用abstract
[访问权限] abstract class 类名 {
成员列表
}
public abstract class Shapes {
public abstract void draw();
}
public abstract class Shapes {
public void draw(){
//具体代码
}
}
抽象类,抽象方法.