7、 面向对象特性

1、准备

对象与类:类是具有类似属性和行为的一类事物的抽象。举例:人是类,那么黄药师就是具体对象。而属性被抽象为类中的成员变量,行为被抽象为成员方法。

成员变量及成员方法:成员变量通常使用private修饰,阻止本类以外的其他类访问。成员与局部变量可以重名,但是需要使用this区分,使用this访问的为成员变量,直接访问的为局部。在方法内访问变量,如果没有该名称的局部变量会自动查找是否有该名称的成员变量。正常定义成员方法时,一般是不需要添加static修饰符的,分为两种:get或set方法和属于类的功能的方法。

成员变量及局部变量区别

类中的位置 内存中的位置 生命周期 初始化值
成员变量 类中,方法外 堆内存 随着对象的创建而存在,随着对象的消失而消失 有默认
局部变量 方法中或者方法声明上(形式参数) 栈内存 随着方法的调用而存在,随着方法的调用完毕而消失 没有默认值。必须先定义,赋值,最后使用

建议同学们查查内存分析图,博客不贴。

2、封装

原则:将不需要对外提供的内容都隐藏起来。把属性隐藏,提供公共方法对其访问。成员变量private,提供对应的get、set方法。

优势:通过方法来控制成员变量的操作,提高了代码的安全性。把代码用方法进行封装,提高了代码的复用性。

private关键字:是一个权限修饰符。可以修饰成员(成员变量和成员方法)。被private修饰的成员只在本类(包括其对象)中才能访问。

this关键字:一般出现在类的一个方法的定义当中,代表当前对象的引用。我们通常用其将本对象中的成员与其他作用域区分开来。

public class StudentTest {
	public static void main(String[] args) {
	Student a=new Student();
	Student b=new Student();
	a.setName("龙王");
	a.setScore(98);
	b.setName("独步王");
	b.setScore(96);
	a.compare(b);
	System.out.println("参赛者:"+b.getName()+"和"+a.getName()+";刀法能力评判分别为:"+b.getScore()+","+a.getScore());
	}
}
	class Student{
	private String name;
	private int score;
	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	public String getScore(){return score;}
	public void setScore(){this.score=score;}
	public void compare(Student s){
	if(this.score>s.score(){
	System.out.println("胜者是:"+this.name);
	}else{System.out.println("胜者是:"+s.name);}
	}
	}

3、继承

概念:如果多个类具有相同的属性和行为,我们可以抽取出共性的内容定义父类,这时再创建相似的类时只要继承父类即可。子类拥有父类的所有属性与方法,无需重新定义。并且可以直接使用非私有的父类成员。举例:父类——动物,子类——猫科、犬科,具体对象——斑点狗。

注意:Java只支持单继承,不支持多继承。即只能有一个父类。父类可以继续有父类。所有类均有父类,只有Object类没有父类。在所有使用父类类型的地方均可以传入其子类对象。构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。

方法重写:子类可以按照子类自身的逻辑重新定义继承过来的父类方法,这个重新定义一个方法的过程叫做方法重写。子类重写方法时,在声明前加@Override可检测该方法是否为重写的方法。访问权限相同或子类方法访问权限更大(访问权限顺序public>默认)。方法名、参数列表、返回值为基本类型时必须相同,返回值为引用类型时相同或子类小。

public class Test{
	public static void main(String[] args) {
	Chinese  c = new Chinese();
	c.setName("张三");//父类继承方法直接调用
	String name = c.getName(); //父类继承方法直接调用
	System.out.println(name); //打印结果为张大力
	c.eat();   //方法重写后调用的为重写后的方法,按照中国的习惯,使用筷子吃
	}
}
	class Person{
	private String name;
	void eat(){System.out.println("吃饭");}
	public String getName(){return name;}
	public void setName(String s){this.name=s;}
	}
	class Chinese extends Person{
	@override //@override是用于强制规定当前定义的方法一定为重写的方法
	public void eat() {System.out.println("按照中国的习惯,使用筷子吃");}
	}

抽象:抽象类用来描述一种类型应该具备的基本特征与功能, 具体如何去完成这些行为由子类通过方法重写来完成。抽象方法指只有功能声明,没有功能主体实现的方法。具有抽象方法的类一定为抽象类。

使用:抽象类无法直接创建对象,只能被子类继承后,创建子类对象。子类需要继承抽象父类并完成最终的方法实现细节(即重写方法,完成方法体)。而此时,方法重写不再是加强父类方法功能,而是父类没有具体实现,子类完成了具体实现,我们将这种方法重写也叫做实现方法。只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。如果存留未实现的抽象方法则该子类仍为一个抽象类,无法创建对象。抽象类不一定包含抽象方法。抽象类可以有非抽象方法。

public class Test {
	public static void main(String[] args) {
	//Animal q = new Animal();抽象类不能创建对象
	Dog d = new Dog();
	d.bark();
	d.sleep();
	d.eat();
	}
}
	abstract class Animal{//abstract在访问权限后,返回值类型前修饰方法,方法没有方法体:
	public abstract void bark()public abstract void sleep();
	public void eat(){System.out.println("吃");}
}
	class Dog extends Animal{
	@Override
	public void bark() {System.out.println("狗汪汪叫!");}
	@Override
	public void sleep() {System.out.println("趴着睡");}
}

4、多态

接口:接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。接口的更为抽象表现为其内的所有方法均为抽象方法,同时不定义普通的成员变量(可以定义静态常量)。

定义:与定义类的class不同,接口定义时需要使用interface关键字。定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。

注意:如同类继承类后便拥有了父类的成员,可以使用父类的非私有成员。A接口继承B接口后,A接口便拥有了A、B两个接口中所有的抽象方法。Java支持一个类同时实现多个接口。 一个类可以有多个接口书写加上逗号即可implements List,RandomAccess,Cloneable。接口中的成员是有固定修饰符abstract的,如果没有写,也会自动加入:(接口中都是常量没有变量)。

public class Test {
	public static void main(String[] args) {
	DrugDog a= new DrugDog();
	a.eat();
	a.bark();
	a.captureDrug();
	}
}
interface CaptureDrug{
	public abstract void captureDrug();
}
abstract class Dog{
	public abstract void eat();
	public void bark(){System.out.println("汪汪");}
	}
class DrugDog extends Dog implements CaptureDrug{
	public void eat(){System.out.println("吃");}
	public void captureDrug(){System.out.println("缉毒");}
}

多态:Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。最终多态体现为父类引用变量可以指向子类对象。多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。多态配合继承与方法重写提高了代码的复用性与扩展性,如果没有方法重写,则多态同样没有意义。

instanceof关键字:通过instanceof关键字来判断某个对象是否属于某种数据类型。
boolean b = 对象 instanceof 数据类型

转型:多态本身是子类类型向父类类型向上转型的过程。向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!

细节:编译时,检查父类引用变量的数据类型是否包含对应的成员方法与成员变量。运行时,成员方法调用子类重写方法,没有用private修饰的成员变量访问时,访问的为父类类型的。

public class Test {
	public static void main(String[] args) {
	Father f= new Father();
	f.method();
	Son s= new Son();
	s.method();
	Father f2= new Son();//多态本身就是向上转型。向上转型后,一切表现形式都是父类的表现形式,不能调用子类特有的功能
	f.method();//打印父类方法
	System.out.println(f2.name);//父亲
	Son s2=(Son)f2;//向下转型,使用强制类型转换进行转换,向下转向那个后可以调用子类特有方法
	s2.method();//打印子类方法
	System.out.println(s2.name);//儿子
	}
}
	class Father{
	String name="父亲";
	public void method(){System.out.println("父类方法");};
}
	class Son extends Father{
	String name="儿子";
	@Override
	public void method(System.out.println("子类方法");){}
}

猜你喜欢

转载自blog.csdn.net/ao__ao/article/details/83010548