JavaSE 07:面向对象三大特性

面向对象三大特性

面向对象的三大特性:封装,继承,多态。

封装

1.概念

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

2.代码示例

Person:

package Day4;
public class Person {
    private String name;
    private int age;
    public Person(){
        this.age=0;
        this.name=null;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void setName(String name){

        this.name=name;
    }
    public String getName(){

        return this.name;
    }
    public void setAge(int age){

        this.age=age;
    }
    public int getAge(){

        return this.age;
    }
    public String toString(){

        return "姓名:"+name+" age:"+age;
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
    Person person=new Person();
    person.setName("lyh");
    person.setAge(21);
        System.out.println(person);
    }
}

继承

1.概念

是面向对象程序设计不可缺少的设计思想,是实现代码可重用的根基,是提高代码可扩展性的主要途径。

继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。

在JAVA中使用extends关键字来表示继承关系。

JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。

继承之后子类可以调用父类的所有非私有属性和非私有方法。

2.super关键字

在子类构造方法中要调用父类的构造方法,需要注意:super语句只能出现在子类构造方法体的第一行。

用“super.成员变量名”来引用父类成员变量。

用“super.方法名(参数列表)”的方式访问父类的方法。

注意:super与this的区别,this通常指代当前对象,super通常指代父类。

3.继承中的构造方法

子类构造方法总是先调用父类构造方法,默认情况下,调用父类无参构造方法。

可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法。

如果用super,必须写在方法的第一句。

如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。

原因:子类创建后需要调用父类的方法,所以在创建子类对象是父类也需要同时被创建。

4.有关继承代码测试

Animal:

package Day4;

public class Animal {
   private String name;
   private  int age;
   public Animal(){
       System.out.println("Animal无参的构造方法!");
   }
   public Animal(String name,int age){
       this();
       this.name=name;
       this.age=age;
       System.out.println("Animal有参的构造方法!");
   }
   public void eat(){
       System.out.println("动物吃");
   }
   public void getInfo(){
       System.out.print("name:"+name+";"+"age:"+age);
   }
}

Dog:

package Day4;
public class Dog extends Animal{
    private String color;
    public Dog(){
        super("",0);
        System.out.println("Dog无参的构造方法!");
    }
    public Dog(String name,int age,String color){
        super(name,age);
        this.color=color;
        System.out.println("Dog有参的构造方法!");
    }

    public void getIn(){
        super.getInfo();
        System.out.println("color:"+color);
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
     Dog dog=new Dog("哈哈哈",3,"黑色");
      dog.getIn();
    }
}
5.方法的重写(方法的覆盖)(OverRide)

在子类中可以根据需要对从基类中继承来的方法进行重写。

方法重写规则:

方法名相同、参数列表相同;

返回值类型相同;

访问权限相同

即与父类方法结构完全相同

注意:构造方法不能重写

当父类的方法实现不能满足子类需求时,可以对方法进行重写( override)。

以上一个案例为主,重写eat方法:

Animal:

package Day4;

public class Animal {
   private String name;
   private  int age;
   public Animal(){
       System.out.println("Animal无参的构造方法!");
   }
   public Animal(String name,int age){
       this();
       this.name=name;
       this.age=age;
       System.out.println("Animal有参的构造方法!");
   }
   public void eat(){
       System.out.println("动物吃");
   }
   public void getInfo(){
       System.out.print("name:"+name+";"+"age:"+age);
   }
}

Dog:

package Day4;
public class Dog extends Animal{
    private String color;
    public Dog(){
        super("",0);
        System.out.println("Dog无参的构造方法!");
    }
    public Dog(String name,int age,String color){
        super(name,age);
        this.color=color;
        System.out.println("Dog有参的构造方法!");
    }
//eat方法的重写
    @Override
    public void eat() {
        super.eat();
        System.out.println("狗吃骨头!");
    }

    public void getIn(){
        super.getInfo();
        System.out.println("color:"+color);
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
     Dog dog=new Dog("哈哈哈",3,"黑色");
      dog.getIn();
      dog.eat();
    }
}
6.关联与依赖

关联是“HAS”关系,依赖是“USE”关系。

A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。

A类依赖B类,指的是B的对象作为A类的方法参数存在,称为“use”关系。

通过以下代码测试依赖关系。

Team:

//根据依赖关系团队有多名学生,而学生也有自己相应的属性
package Day5;
import java.util.Arrays;
public class Team {
   private String subject;
   private Student[] student;
   public Team(Student[] student) {

       this.student = student;
   }

   public String getSubject() {

       return subject;
   }

   public void setSubject(String subject) {

       this.subject = subject;
   }

   public Student[] getStudent() {
       return student;
   }

   public void setStudent(Student[] student) {
       this.student = student;
   }

   @Override
   public String toString() {
       return "Team{" +
               "subject='" + subject + '\''+

               ","+" student=" + Arrays.toString(student) +
               '}';
   }
}

Student:

package Day5;

public class Student {
  private  String  id;
  private String name;
  private int age;
    public Student(){
    this.id=null;
    this.name=null;
    }
    public Student(String id,String name,int age){
    this.name=name;
    this.id=id;
    this.age=age;
    }
    public String getId() {

        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

该团队有5名学生,并输出学生基本信息。

Test:

package Day5;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        Student student[]=new Student[5];
        student[0]=new Student("1822","cjr",21);
        student[1]=new Student("1823","cyx",21);
        student[2]=new Student("1825","lyh",23);
        student[3]=new Student("1820","ccc",22);
        student[4]=new Student("1827","jij",25);
        Team team=new Team(student);
        team.setSubject("智能算法");
        System.out.println(team);
        System.out.println(Arrays.toString(student));
        System.out.println(Arrays.toString(team.getStudent()));
    }
}

多态

1.概念

同一种事物,在不同时刻表现不同的状态

多态存在的三个必要条件

要有继承(包括接口的实现)(前提条件)

要有重写(前提条件)

父类引用指向子类对象

Animal:

package Day5;
public class Animal {
   private String name;
   private int age;
   public void eat(){
       System.out.println("Animal吃");
   }
  public static  void say(){
      System.out.println("Animal叫");
  }
    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;
    }
}

Dog:

package Day5;

public class Dog extends Animal{
    private String type;
    public void eat(){
        System.out.println("Dog吃骨头");
    }
    public static void say(){
        System.out.println("Dog旺旺");
    }
   public void sleep(){
       System.out.println("Dog睡觉");
   }
}

Cat:

package Day5;

public class Cat extends Animal{
    private String type;
    public void eat(){
        System.out.println("cat吃饭");
    }
    public static void say(){
        System.out.println("Cat喵喵");
    }
    public void study(){
        System.out.println("Cat学习");
    }
}

Test:

package Day5;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test {
    //多态的体现
    public void run(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        Test test=new Test();
     Animal  dog=new Dog();
     dog.eat();//编译看左边,运行看右边。eat方法被重写
     dog.say();//静态方法编译运行看左边,因为静态变量静态方法都存储在方法区。
     Dog dog0=(Dog)dog;//建议在使用向下转型的时候考虑使用instanceof判断是否为该类型,避免异常。
     dog0.sleep();
     dog0.eat();
     Animal cat=new Cat();
     cat.eat();
     Cat cat0=(Cat)cat;
     cat0.eat();
     cat0.study();
     test.run(cat);
     test.run(dog);
    }
}

注意:对于静态方法没有必要去重写,静态方法,成员变量都是编译运行看左边。

静态加载优先于main方法。

2.final关键字

final 用于声明属性,方法和类

属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能修改。

方法:子类里不可被覆盖(重写)。

类:不能被定义为抽象类或是接口,不可被继承。

在声明时同时赋值,往往与static一起使用

声明时不赋值,必须在构造方法中逐一赋值

总的原则:保证创建每一个对象的时候,final属性的值是确定的。

在方法参数前面加final关键字,为了防止数据在方法体中被修改。

package Day5;
public class keyword_final {
    final static int  acc=10;//必须赋值
    static int num0;
       final  int num;//可以在构造方法中赋值
       public keyword_final(int num){
           this.num=num;
       }
       public void test(){
           final int num;

       }
    public static void main(String[] args) {
        keyword_final key0=new keyword_final(10);
        keyword_final key1=new keyword_final(11);
    }
}
package Day5;
public class keyword_final {
    final static int a=0;//final定义的变量如果是成员变量必须初始化。
    public static void main(String[] args) {
    final int b=10;
        System.out.println(a);
        //此调用涉及静态方法只能调用静态静态标量或者静态方法。所以a必须是静态变量类似于递归算法。
    }
}
3.抽象类

用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。

抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。

抽象方法必须用abstract关键字进行修饰。

抽象类可以有成员属性和非抽象的成员方法。

抽象类不能被实例化,但可以有构造函数,因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。

抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。否则,该类也必须声明为抽象类。

构造方法和静态方法不可以修饰为abstract。

Shape:

package Day5;

public abstract class Shape {
    int name;
    public abstract double getArea();//定义抽象方法 求面积 无方法体只声明不实现 抽象类不能被实例化只能通过子类实现。
    public abstract  double getPerimeter();//求周长
}

Circle:

package Day5;
public class Circle extends Shape {
    private double r;
    public double getR() {
        return r;
    }
    public void setR(double r) {
        this.r = r;
    }
    @Override
    public double getArea() {
        return Math.PI*r*r;
    }
    @Override
    public double getPerimeter() {
        return 2*Math.PI*r;
    }
}

Rectangle:

package Day5;

public class Rectangle extends Shape{
    private double length;
    private double width;
    public double getWidth() {
        return width;
    }
    public void setWidth(double width) {
        this.width = width;
    }
    public double getLength() {
        return length;
    }
    public void setLength(double length) {
        this.length = length;
    }
    @Override
    public double getPerimeter() {
       return (length+width)*2;
    }
    @Override
    public double getArea() {
       return length*width;
    }
}

Test:

package Day5;
import java.util.*;
public class Test {
    public void run(Shape shape) {
        System.out.println("面积:"+shape.getArea());
        System.out.println("周长"+shape.getPerimeter());
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Test test=new Test();
        System.out.println("请输入圆的半径:");
        double r=sc.nextDouble();
        Shape circle=new Circle();
        Circle c=(Circle)circle;
        c.setR(r);
        System.out.println("半径为:"+r+"的圆:");
        test.run(circle);
        System.out.println("请输入长方形的长:");
        double length=sc.nextDouble();
        System.out.println("请输入长方形的宽:");
        double width=sc.nextDouble();
        Shape rectangle=new Rectangle();
        System.out.println("长度为"+length+"宽度为"+width+"的长方形:");
        Rectangle re=(Rectangle) rectangle;
        re.setLength(length);
        re.setWidth(width);
        test.run(rectangle);
    }
    }

instanceof在此案例中的测试出现警告

因为此案例中结果返回值一直是true。

只是修改了上一个案例的Test类方法。

package Day5;
import java.util.*;
public class Test {
    public void run(Shape shape) {
        System.out.println("面积:"+shape.getArea());
        System.out.println("周长"+shape.getPerimeter());
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Test test=new Test();
        System.out.println("请输入圆的半径:");
        double r=sc.nextDouble();
        Shape circle=new Circle();
        if(circle instanceof Circle) {
            Circle c = (Circle) circle;
            c.setR(r);
            System.out.println("半径为:" + r + "的圆:");
            test.run(circle);
        }
        System.out.println("请输入长方形的长:");
        double length=sc.nextDouble();
        System.out.println("请输入长方形的宽:");
        double width=sc.nextDouble();
        Shape rectangle=new Rectangle();
        System.out.println("长度为"+length+"宽度为"+width+"的长方形:");
        if(rectangle instanceof Rectangle) {
            Rectangle re = (Rectangle) rectangle;
            re.setLength(length);
            re.setWidth(width);
            test.run(rectangle);
        }
    }
    }
4.接口

接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。

接口中每一个方法也是隐式抽象的,默认为public abstract 。

接口中声明的属性默认为 public static final 的。

接口不是被类继承了,而是要被类实现。

接口不能实例化对象(无构造方法),但可以声明对象的引用。(多态性)

多个类可以实现同一个接口。

一个类可以实现多个接口,但只能继承一个类。

与继承关系类似,接口与实现类之间存在多态性。

一个接口能继承其它多个接口。

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

5.抽象类与接口的区别

语法上的区别

1。抽象类里可以有构造方法,而接口内不能有构造方法。

2。抽象类中可以有普通成员变量,而接口中不能有普通成员变量。

3。抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的。

4。抽象类中的抽象方法的访问类型可以是public ,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5。抽象类中可以包含静态方法,接口内不能包含静态方法。

6。抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义 静态常量。

相同点

1。抽象类和接口都不能用来创建对象。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值