欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

7、 面向对象特性

程序员文章站 2024-03-15 20:21:06
...

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("子类方法");){}
}
相关标签: java基础学习笔记