十三、 封装、继承和多态

一句废话都没有的Pycharm(十三):封装、继承、多态及特殊属性和方法 一句废话都没有的Pycharm(十二):面向对象的封装、继承、多态及特殊属性和方法 介绍 1.编程思想 1.1 面形对象 1.1.1. 封装 1.1.2 继承 1.1.3 多态 1.1.4 特殊属性和方法 1.编程思想 首先我们要明确两大编程思想:面向过程和面形对象。 通俗来解释一下它们,我现在想吃佛跳墙,面向过程指的就是我自己按照烹饪的步骤一步一步去做;面向对象就是我直接去饭店,点了一份佛跳墙。这两种编程思想并不冲突,而是相辅相成的。 当遇到的对象比较简单时,我们很容易通过面性过程自己去解 阅读详情

第1关:什么是封装,如何使用封装


任务描述
本关任务:构造一个类,把对象的属性封装起来,同时提供一些可以被外界访问属性的方法。

相关知识
为了完成本关任务,你需要掌握:1.什么是封装;2.封装的意义;3.实现Java封装的步骤。

什么是封装
封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装时的权限控制符区别如下:
在这里插入图片描述

封装的意义
对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有四大好处:

良好的封装能够减少耦合。
类内部的结构可以自由修改。
可以对成员进行更精确的控制。
隐藏信息,实现细节。
封装把一个对象的属性私有化,同时提供一些可以被外界访问属性的方法,如果不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
#####实现Java封装的步骤

修改属性的可见性来限制对属性的访问(一般限制为private),例如:

public class Person {
 private String name;
 private int age;
}

这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。

对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:

/*
*封装演示
*/
public class Person {
    /*
     * 对属性的封装 一个人的姓名、性别和年龄都是这个人的私有属性
     */
    private String name;
    private String sex;
    private int age;
    /*
     * setter()、getter()是该对象对外开放的接口
     */
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

封装可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码,就可以对成员变量进行更精确的控制。

public void setAge(int age) {
    if (age > 120) {
        System.out.println("ERROR:error age input...."); // 提示错误信息
    } else {
        this.age = age;
    }
}
public String getSexName() {
    if ("0".equals(sex)) {
        sexName = "女";
    } else if ("1".equals(sex)) {
        sexName = "男";
    } else {
        sexName = "人妖";
    }
    return sexName;
}

编程要求
根据提示,在右侧编辑器Begin-End处补充代码:

声明一个Person类,私有化属性name和age,并将字段封装起来;

在Person类中定义一个talk()方法,打印姓名和年龄信息;

在main方法中声明并实例化一Person对象p,给p中的属性赋值,调用talk()方法打印

 我是:张三,今年:18岁。

测试说明
测试输入: 无
预期输出:

我是:张三,今年:18岁

代码实现

package case1;
public class TestPersonDemo {
	public static void main(String[] args) {
		/********* begin *********/
		// 声明并实例化一Person对象p
      Person p=new Person();
		// 给p中的属性赋值
             String name=p.getName();
			 name="张三";
			 p.setName(name);
			 int age=p.getAge();
			 age=18;
			 p.setAge(age);
		// 调用Person类中的talk()方法
             p.talk();
		/********* end *********/

	}
}
// 在这里定义Person类
class Person {
	/********* begin *********/
         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;
		 }
		 public void talk(){
			 System.out.print("我是:"+name+",今年:"+age+"岁");
		 }
	/********* end *********/
}

第2关:什么是继承,怎样使用继承


任务描述
本关任务:掌握继承的基本概念以及怎么使用继承。

相关知识
为了完成本关任务,你需要掌握:1.继承的基本概念;2.继承的特性;3.子类对象的实例化过程。

继承的基本概念
所谓继承:是指可以让某个类型的对象获得另一个类型的对象的属性的方法。
在这里插入图片描述

兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。

在讲解继承的基本概念之前,读者可以先想一想这样一个问题:现在假设有一个Person类,里面有name与age两个属性,而另外一个Student类,需要有name、age、school三个属性,如图所示,从这里可以发现Person中已经存在有name和age两个属性,所以不希望在Student类中再重新声明这两个属性,这个时候就需要考虑是不是可以将Person类中的内容继续保留到Student类中,也就是引出了接下来所要介绍的类的继承概念。
在这里插入图片描述

在这里希望Student类能够将 Person类的内容继承下来后继续使用:

在这里插入图片描述

Java类的继承,可用下面的语法来表示:

class 父类 // 定义父类
{
    ...
}
class 子类 extends 父类 // 用extends关键字实现类的继承
{
    ...
}

范例:

public class TestPersonStudentDemo {
    public static void main(String[] args) {
        Student s = new Student();
        // 访问Person类中的name属性
        s.name = "张三";
        // 访问Person类中的age属性
        s.age = 18;
        // 访问Student类中的school属性
        s.school = "哈佛大学";
        System.out.println("姓名:" + s.name + ",年龄:" + s.age + ",学校:" + s.school);
    }
}
class Person {
    String name;
    int age;
}
class Student extends Person {
    String school;
}

输出结果:

姓名:张三,年龄:18,学校:哈佛大学

由上面的程序可以发现,在Student类中虽然并未定义name与age属性,但在程序外部却依然可以调用name或age,这是因为Student类直接继承自Person类,也就是说Student类直接继承了Person类中的属性,所以Student类的对象才可以访问到父类中的成员。
在这里插入图片描述

继承的特性
子类拥有父类非private的属性和方法;

子类可以拥有自己的属性和方法,即子类可以对父类进行扩展;

子类可以用自己的方式实现父类的方法;

在Java中只允许单继承,而不允许多重继承,也就是说一个子类只能有一个父类,但是Java中却允许多层继承,多层继承就是,例如类C继承类B,类B继承类A,所以按照关系就是类A是类B的父类,类B是类C的父类,这是Java继承区别于C++继承的一个特性;

提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。

多重继承:
在这里插入图片描述

class A{
    ...
}
class B{
    ...
}
class C extends A,B{
    ...
}

由上面可以发现类C同时继承了类A与类B,也就是说类C同时继承了两个父类,这在Java中是不允许的。
多层继承:
在这里插入图片描述

class A{
    ...
}
class B extends A{
    ...
}
class C extends B{
    ...
}

由上面可以发现类B继承了类A,而类C又继承了类B,也就是说类B是类A的子类,而类C则是类A的孙子类。

子类对象的实例化过程
既然子类可以继承直接父类中的方法与属性,那父类中的构造方法呢?请看下面的范例:

public class TestPersonStudentDemo1 {
    public static void main(String[] args) {
        Student s = new Student();
    }
}
class Person {
    String name;
    int age;
    // 父类的构造方法
    public Person() {
        System.out.println("1.public Person(){}");
    }
}
class Student extends Person {
    String school;
    // 子类的构造方法
    public Student() {
        System.out.println("2.public Student(){}");
    }
}

输出结果:

1.public Person(){}
2.public Student(){}

从程序输出结果中可以发现,虽然程序第3行实例化的是子类的对象,但是程序却先去调用父类中的无参构造方法,之后再调用了子类本身的构造方法。所以由此可以得出结论,子类对象在实例化时会默认先去调用父类中的无参构造方法,之后再调用本类中的相应构造方法。
实际上在本范例中,在子类构造方法的第一行默认隐含了一个super()语句,上面的程序如果改写成下面的形式,也是可以的:

class Student extends Person{
    String school ;
    // 子类的构造方法
    public Student(){
        super() ; //实际上在程序的这里隐含了这样一条语句
        System.out.println("2.public Student(){}");
    }
}

继承条件下构造方法调用规则如下:

如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显示调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下写不写super()语句效果都是一样;

如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法;

如果子类的构造方法中通过this显示调用自身的其他构造方法,在相应构造方法中应用以上两条规则;

特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。

编程要求
根据提示,在右侧编辑器Begin-End处补充代码:

声明一个Animal类,将属性name和age封装起来,提供对外的公共访问方法;

声明一个Cat类和Dog类,都继承Animal类,分别定义各自的voice方法和eat方法;

在main方法中分别实例化一个Cat对象和Dog对象,设置各自的属性并调用这两个方法,再打印出名字和年龄信息;

具体具体输出要求请看测试说明。

测试说明
测试输入:无
预期输出:

大花猫喵喵叫
大花猫吃鱼
大花猫6岁
大黑狗汪汪叫
大黑狗吃骨头
大黑狗8岁

代码实现

package case2;
public class extendsTest {
	public static void main(String args[]) {
		// 实例化一个Cat对象,设置属性name和age,调用voice()和eat()方法,再打印出名字和年龄信息
		/********* begin *********/
              Cat c=new Cat("大花猫",6);
			  c.voice();
			  c.eat();
			  c.show();
		/********* end *********/
		// 实例化一个Dog对象,设置属性name和age,调用voice()和eat()方法,再打印出名字和年龄信息
		/********* begin *********/
             Dog d=new Dog("大黑狗",8);
			 d.voice();
			 d.eat();
			 d.show();
		/********* end *********/
	}
}
class Animal {
	/********* begin *********/
           String name;
		   int age;
	/********* end *********/
}
class Cat extends Animal {
	// 定义Cat类的voice()和eat()方法
	/********* begin *********/
          Cat(String name,int age){
			  this.name=name;
			  this.age=age;
		  }
			  void voice(){
				  System.out.println(name+"喵喵叫");
			  }
			  void eat(){
				  System.out.println(name+"吃鱼");
			  }
			  void show(){
				  System.out.println(name+age+"岁");
			  }
 	  
	/********* end *********/
}
class Dog extends Animal {
	// 定义Dog类的voice()和eat()方法
	/********* begin *********/
          Dog(String name,int age){
			  this.name=name;
			  this.age=age;
		  }
			  void voice(){
				  System.out.println(name+"汪汪叫");
			  }
			  void eat(){
				  System.out.println(name+"吃骨头");
			  }
			  void show(){
				  System.out.println(name+age+"岁");
			  }
	/********* end *********/
}

第3关:super关键字的使用


任务描述
本关任务:掌握super关键字的使用。

相关知识
为了完成本关任务,你需要掌握:1.super关键字;2.super关键字的使用;3.super与this关键字的比较。

super关键字
在上一节中曾经提到过super的使用,那super到底是什么呢?super关键字出现在子类中,我们new子类的实例对象的时候,子类对象里面会有一个父类对象。怎么去引用里面的父类对象呢?使用super来引用,所以可以得出结论:super主要的功能是完成子类调用父类中的内容,也就是调用父类中的属性或方法。
super关键字的使用

super关键字的用法如下:

super可以用来引用直接父类的实例变量。
super可以用来调用直接父类方法。
super()可以用于调用直接父类构造函数。
1.super用于引用直接父类实例变量

public class TestSuper1 {
    public static void main(String args[]) {
        Dog d = new Dog();
        d.printColor();
    }
}
class Animal {
    String color = "white";
}
class Dog extends Animal {
    String color = "black";
    void printColor() {
        System.out.println(color);// prints color of Dog class
        System.out.println(super.color);// prints color of Animal class
    }
}

输出结果:

black
white

在上面的例子中,Animal和Dog都有一个共同的属性:color。 如果我们打印color属性,它将默认打印当前类的颜色。要访问父属性,需要使用super关键字指定。

2.通过super来调用父类方法

public class TestSuper2 {
    public static void main(String args[]) {
        Dog d = new Dog();
        d.work();
    }
}
class Animal {
    void eat() {
        System.out.println("eating...");
    }
}
class Dog extends Animal {
    void eat() {
        System.out.println("eating bread...");
    }
    void bark() {
        System.out.println("barking...");
    }
    void work() {
        super.eat();
        bark();
    }
}

输出结果:

eating...
barking...

在上面的例子中,Animal和Dog两个类都有eat()方法,如果要调用Dog类中的eat()方法,它将默认调用Dog类的eat()方法,因为当前类的优先级比父类的高。所以要调用父类方法,需要使用super关键字指定。

3.使用super来调用父类构造函数

public class TestSuper3 {
    public static void main(String args[]) {
        Dog d = new Dog();
    }
}
class Animal {
    Animal() {
        System.out.println("animal is created");
    }
}
class Dog extends Animal {
    Dog() {
        super();
        System.out.println("dog is created");
    }
}

输出结果

animal is created
dog is created

注意:如果没有使用super()或this(),则super()在每个类构造函数中由编译器自动添加。

super与this关键字的比较
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
范例:

public class TestAnimalDogDemo {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();
        Dog d = new Dog();
        d.eatTest();
    }
}
class Animal {
    void eat() {
        System.out.println("animal : eat");
    }
}
class Dog extends Animal {
    void eat() {
        System.out.println("dog : eat");
    }
    void eatTest() {
        this.eat(); // this 调用自己的方法
        super.eat(); // super 调用父类方法
    }
}

输出结果:

animal : eat
dog : eat
animal : eat

上表对 this 与 super 的差别进行了比较,从上表中不难发现,用 super 或 this 调用构造方法时都需要放在首行,所以super 与 this 调用构造方法的操作是不能同时出现的。
编程要求
comment: <> (“编程要求”部分介绍本关任务的具体要求,如实现步骤,规则等,最好能给出效果图)
根据提示,在右侧编辑器Begin-End处补充代码:

声明一个名为Person的类,里面有name与age两个属性,并声明一个含有两个参数的构造方法;

声明一个名为Student的类,此类继承自Person类,添加一个属性school,在子类的构造方法中调用父类中有两个参数的构造方法;

实例化一个Student类的对象s,为Student对象s中的school赋值,打印输出姓名:

测试说明
测试输入:无
预期输出:

姓名:张三,年龄:18,学校:哈佛大学

代码实现

package case3;

public class superTest {
	public static void main(String[] args) {
		// 实例化一个Student类的对象s,为Student对象s中的school赋值,打印输出信息
		/********* begin *********/
        Student s=new Student();
        s.school="哈佛大学";
        System.out.println("姓名:"+s.name+",年龄:"+s.age+",学校:"+s.school);
		/********* end *********/
	}
}

class Person {
	/********* begin *********/
     String name;
	 int age;
     public Person(String name,int age){
         this.name=name;
         this.age=age;
     }
	/********* end *********/
}

class Student extends Person {
	/********* begin *********/
    String school;
      public Student(){
          super("张三",18);
      }

	/********* end *********/
}

第4关:方法的重写与重载


任务描述
本关任务:掌握方法的重写与重载。

相关知识
为了完成本关任务,你需要掌握:1.方法的重写(override);2.方法的重载(overload);3.重写与重载之间的区别。

方法的重写(override)
方法的重写

子类从父类中继承方法,有时,子类需要修改父类中定义的方法的实现,这称做方法的重写(method overriding)。“重写”的概念与“重载”相似,它们均是Java“多态”的技术之一,所谓“重载”,即是方法名称相同,但却可在不同的场合做不同的事。当一个子类继承一父类,而子类中的方法与父类中的方法的名称、参数个数和类型都完全一致时,就称子类中的这个方法重写了父类中的方法。“重写”又称为“复写”、“覆盖”。

如何使用重写

class Super {
 访问权限 方法返回值类型 方法1(参数1) {
     ...
 }
}
class Sub extends Super{
 访问权限 方法返回值类型 方法1(参数1) —————>复写父类中的方法
 {
     ...
 }
}

注意:方法重写时必须遵循两个原则,否则编译器会指出程序出错。

重写的方法不能比被重写的方法有更严格的访问权限;

重写的方法不能比被重写的方法产生更多的异常(关于异常,在后面会介绍)。

编译器加上这两个限定,是为了与Java语言的多态性(关于方法重写引起的运行时多态,在后面会详细讲述)特点一致而做出的。这样限定是出于对程序健壮性的考虑,为了避免程序执行过程中产生访问权限冲突或有应该捕获而未捕获的异常产生。

方法的重载(overload)
方法的重载

首先回顾一下前面所讲的方法的重载,方法重载是指多个方法可以享有相同的名字,但是参数的数量或类型不能完全相同。
调用方法时,编译器根据参数的个数和类型来决定当前所使用的方法。方法重载为程序的编写带来方便,是OOP多态性的具体变现。在Java系统的类库中,对许多重要的方法进行重载,为用户使用这些方法提供了方便。

重载的规则

被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
被重载的方法可以改变访问修饰符;
被重载的方法可以声明新的或更广的检查异常;
方法能够在同一个类中或者在一个子类中被重载。
无法以返回值类型作为重载函数的区分标准。
重写与重载之间的区别
在这里插入图片描述

方法的重写和重载是Java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载;

方法重写是在子类存在方法与父类的方法的名字相同而且参数的个数与类型一样,返回值也一样的方法,就称为方法的重写;

方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

在这里插入图片描述
在这里插入图片描述

编程要求
根据提示,在右侧编辑器补充代码。

声明一个名为Person的类,里面声明name与age两个属性,定义talk()方法返回姓名和年龄信息;

声明一个名为Student的类,此类继承自Person类,添加school属性,声明带三个参数的构造方法,复写talk()方法,在该方法中调用父类的talk()方法,返回姓名、年龄和学校信息;

实例化子类对象s,调用talk()方法打印我是:张三,今年:18岁,我在哈佛大学上学。

测试说明
测试输入: 无
预期输出:

代码实现

package case4;
public class overridingTest {
	public static void main(String[] args) {
		// 实例化子类对象s,调用talk()方法打印信息
		/********* begin *********/
             Student s=new Student("张三",18,"哈佛大学");
			 s.talk();
		/********* end *********/	
	}
}
class Person {
	/********* begin *********/
    public String name;
	public int age;
	 void talk(){
        System.out.println("我是:"+name+",今年:"+age+"岁");
	 }
	/********* end *********/
}
class Student extends Person {
	/********* begin *********/
       private String school;
	   public Student(String name,int age,String school){
			  this.name=name;
			  this.age=age;
			  this.school=school;
		  }
		  void talk(){
			  System.out.print("我是:"+name+",今年:"+age+"岁,我在"+school+"上学");
		  }
	/********* end *********/
}

第5关:抽象类


任务描述
本关任务:掌握抽象类的定义及用法。

相关知识
为了完成本关任务,你需要掌握:1.抽象类的概念;2.如何定义抽象类。

抽象类的概念
前面对类的继承进行了初步的讲解。通过继承,可以从原有的类派生出新的类。原有的类称为基类或父类,而新的类则称为派生类或子类。通过这种机制,派生出的新的类不仅可以保留原有的类的功能,而且还可以拥有更多的功能。

除了上述的机制之外,Java也可以创建一种类专门用来当作父类,这种类称为“抽象类”。抽象类的作用有点类似“模版”,其目的是要设计者依据它的格式来修改并创建新的类。但是并不能直接由抽象类创建对象,只能通过抽象类派生出新的类,再由它来创建对象。

如何定义抽象类
抽象类的定义规则:

抽象类和抽象方法都必须用abstract关键字来修饰;

抽象类不能被实例化,也就是不能用new关键字去产生对象;

抽象方法只需声明,而不需实现;

含有抽象方法的类必须被声明为抽象类,抽象类的子类必须复写所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。

抽象类的定义格式:

abstract class 类名称 // 定义抽象类
{
    声明数据成员;
    访问权限 返回值的数据类型 方法名称(参数...)//定义一般方法
    {
        ...
    }
    abstract 返回值的数据类型 方法名称(参数...);
    //定义抽象方法,在抽象方法里,没有定义方法体
}

注意:

在抽象类定义的语法中,方法的定义可分为两种:一种是一般的方法,它和先前介绍过的方法没有什么两样;另一种是“抽象方法”,它是以abstract关键字为开头的方法,此方法只声明了返回值的数据类型、方法名称与所需的参数,但没有定义方法体。
抽象类也可以像普通类一样,有构造方法、一般方法、属性,更重要的是还可以有一些抽象方法,留给子类去实现,而且在抽象类中声明构造方法后,在子类中必须明确调用。
编程要求
根据提示,在右侧编辑器补充代码:

声明一个名为Person的抽象类,在Person类中声明了三个属性name、age和occupation和一个抽象方法talk();

声明一个Student类和一个Worker类,都继承自Person类,添加带有三个参数的构造方法;

分别实例化Student类与Worker类的对象,分别调用各自类中被复写的talk()方法打印输出信息;

具体输出要求请看测试说明。

测试说明
测试输入: 无
预期输出:

学生——>姓名:张三,年龄:20,职业:学生!
工人——>姓名:李四,年龄:30,职业:工人!

代码实现

package case5;
public class abstractTest {
	public static void main(String[] args) {
		/********* begin *********/
		// 分别实例化Student类与Worker类的对象,并调用各自构造方法初始化类属性。
		   Student s=new Student("张三",20,"学生");
		   Worker w=new Worker("李四",30,"工人" );
		// 分别调用各自类中被复写的talk()方法 打印信息。
		     s.talk();
			 w.talk();
	}
}
// 声明一个名为Person的抽象类,在Person中声明了三个属性name age occupation和一个抽象方法——talk()。
abstract class Person {
	/********* begin *********/
     String name;
	 int age;
	 String occupation;
	  abstract  void talk();
	/********* end *********/
}
// Student类继承自Person类,添加带三个参数的构造方法,复写talk()方法 返回姓名、年龄和职业信息
class Student extends Person {
	/********* begin *********/
     public  Student(String name,int age,String occupation){
            this.name=name;
		this.age=age;
		this.occupation=occupation;
	   }
	 void talk(){
	System.out.println("学生——>姓名:"+name+",年龄:"+age+",职业:"+occupation+"!");
		}
	/********* end *********/
}
// Worker类继承自Person类,添加带三个参数的构造方法,复写talk()方法 返回姓名、年龄和职业信息
class Worker extends Person {
	/********* begin *********/
   public Worker(String name,int age,String occupation){
		this.name=name;
		this.age=age;
		this.occupation=occupation;
	}
	   void talk(){
		   System.out.println("工人——>姓名:"+name+",年龄:"+age+",职业:"+occupation+"!");
	   }
	/********* end *********/

}

第6关:final关键字的理解与使用


任务描述
本关任务:理解并能正确使用final关键字。

相关知识
为了完成本关任务,你需要掌握:1.final关键字的使用; 2.final关键字修饰类、成员变量和成员方法。

final关键字的使用
在Java中声明类、属性和方法时,可使用关键字final来修饰。

final标记的类不能被继承;

final标记的方法不能被子类复写;

final标记的变量(成员变量或局部变量)即为常量,只能赋值一次。

final关键字修饰类、成员变量和成员方法
1.final类

final用来修饰一个类,意味着该类成为不能被继承的最终类。出于安全性的原因和效率上的考虑,有时候需要防止一个类被继承。例如,Java类库中的String类,它对编译器和解释器的正常运行有着很重要的作用,不能轻易改变它,因此把它修饰为final类,使它不能被继承,这就保证了String类的惟一性。同时,如果你认为一个类的定义己经很完美,不需要再生成它的子类,这时也应把它修饰为final类。
定义一个final类的格式如下:

final class ClassName{
    ...
}

注意:声明为final的类隐含地声明了该类的所有方法为final方法。

下面的结论是成立的:声明一个类既为abstract,又为final是非法的,因为抽象类必须被子类继承来实现它的抽象方法。下面是一个final类的例子:

final class A{
    ...
}
class B extends A{//错误!不能继承A
    ...
}

2.final修饰成员变量
变量被声明为final后,成为常值变量(即常量),一旦被通过某种方式初始化或赋值,即不能再被修改。通常static与final一起使用来指定一个类常量。例如:

static final int SUNDAY=0;

把final变量用大写字母和下划线来表示,这是一种编码规定。

3.final修饰成员方法
用final修饰的方法为最终方法,不能再被子类重写,可以被重载。
尽管方法重写是Java非常有力的特征,但有时却需要避免这种情况的发生。为了不允许一个方法被重写,在方法的声明中指定final属性即可。例如:

class A{
    final void method(){}
}
class B extends A{//定义A类的一个子类B
    void method(){}//错误,method()不能被重写
}

该例中,因为method()方法在A中被声明为final,所以不能在子类B中被重写。如果这样做,将导致编译错误。
方法被声明为final有时可以提高性能:编译器可以自由地内联调用它们,因为它“知道”它们不会被子类重写。

编程要求
根据提示,在右侧编辑器Begin-End处补充代码:

仔细阅读代码,在右侧编辑器中调整代码使程序能正确编译运行;

具体输出要求请看测试说明。

测试说明
测试输入:无
预期输出:

speedlimit=120
running safely with 100kmph
running safely with 100kmph

代码实现

package case6;
public class finalTest {
	public static void main(String args[]) {
		Bike1 obj = new Bike1();
		obj.run();
		Honda honda = new Honda();
		honda.run();
		Yamaha yamaha = new Yamaha();
		yamaha.run();
	}
}
//不可以修改 final 变量的值
// final方法,不可以重写
 //不可以扩展 final 类
//请在此添加你的代码
    /********** Begin *********/
	class Bike1 {
	final int speedlimit = 90;
	void run() {
		System.out.println("speedlimit=120");
	}
}
class Bike2 {
	 void run() {
		System.out.println("running");
	}
}
class Honda extends Bike2 {
	void run() { 
		System.out.println("running safely with 100kmph");
	}
}
 class Bike3 {
}
class Yamaha extends Bike3 { 
	void run() {
		System.out.println("running safely with 100kmph");
	}
}
    /********** End **********/

第7关:接口


任务描述
本关任务:掌握接口相关的知识。

相关知识
为了完成本关任务,你需要掌握:1.接口的定义; 2.接口的实现; 3.接口的扩展。

接口的定义
接口(interface)是Java所提供的另一种重要技术,它的结构和抽象类非常相似,也具有数据成员与抽象方法,但它与抽象类又有以下两点不同:

接口里的数据成员必须初始化,且数据成员均为常量;

接口里的方法必须全部声明为abstract,也就是说,接口不能像抽象类一样保有一般的方法,而必须全部是“抽象方法”。

接口定义的语法如下:

interface 接口名称 // 定义抽象类
{
    final 数据类型 成员名称 = 常量; //数据成员必须赋初值
    abstract 返回值的数据类型 方法名称(参数...);
    //抽象方法,注意在抽象方法里,没有定义方法主体
}

接口与一般类一样,本身也具有数据成员与方法,但数据成员一定要赋初值,且此值将不能再更改,方法也必须是“抽象方法”。也正因为方法必须是抽象方法,而没有一般的方法,所以抽象方法声明的关键字abstract是可以省略的。

相同的情况也发生在数据成员身上,因数据成员必须赋初值,且此值不能再被更改,所以声明数据成员的关键字final也可省略。事实上只要记得:

接口里的“抽象方法”只要做声明即可,而不用定义其处理的方式;

数据成员必须赋初值。

接口的实现
在Java中接口是用于实现多继承的一种机制,也是Java设计中最重要的一个环节,每一个由接口实现的类必须在类内部复写接口中的抽象方法,且可自由地使用接口中的常量。
既然接口里只有抽象方法,它只要声明而不用定义处理方式,于是自然可以联想到接口也没有办法像一般类一样,再用它来创建对象。利用接口打造新的类的过程,称之为接口的实现(implementation)。

接口实现的语法:

class 类名称 implements 接口A,接口B //接口的实现
{
    ...
}

接口的扩展
接口是Java实现多继承的一种机制,一个类只能继承一个父类,但如果需要一个类继承多个抽象方法的话,就明显无法实现,所以就出现了接口的概念。一个类只可以继承一个父类,但却可以实现多个接口。

接口与一般类一样,均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口,派生出的接口称为派生接口或子接口。通过这种机制,派生接口不仅可以保留父接口的成员,同时也可加入新的成员以满足实际的需要。

同样的,接口的扩展(或继承)也是通过关键字extends来实现的。有趣的是,一个接口可以继承多个接口,这点与类的继承有所不同。

接口扩展的语法:

interface 子接口名称 extends 父接口1,父接口2...
{
    ...
}

编程要求
根据提示,在右侧编辑器补充代码:

声明一Person接口,并在里面声明三个常量:name、age、occupation,并分别赋值;

声明一Student类,此类实现Person接口,并复写Person中的talk()方法;

实例化一Student的对象s,并调用talk()方法,打印信息;

具体输出要求请看测试说明。

测试说明
测试输入:无
预期输出:

学生——>姓名:张三,年龄:18,职业:学生!

代码实现

package case7;

public class interfaceTest {
	public static void main(String[] args) {
		// 实例化一Student的对象s,并调用talk()方法,打印信息
		/********* begin *********/
        Student s = new Student();
        System.out.print(s.talk());
		/********* end *********/

	}
}

// 声明一个Person接口,并在里面声明三个常量:name、age和occupation,并分别赋值,声明一抽象方法talk()
interface Person {
	/********* begin *********/
    final String name = "张三";
    final int age = 18;
    final String occupation="学生";
    public abstract String talk();
	/********* end *********/
}

// Student类继承自Person类 复写talk()方法返回姓名、年龄和职业信息
class Student implements Person {
	/********* begin *********/
public String talk(){
  return   "学生——>姓名:"+this.name+",年龄:"+this.age+",职业:"+this.occupation+"!";
	/********* end *********/
}
}

第8关:什么是多态,怎么使用多态


任务描述
本关任务:掌握对象的多态性。

相关知识
为了完成本关任务,你需要掌握:1.什么是多态;2.多态的实现条件;3.多态的实现形式。

什么是多态
所谓多态:就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
在这里插入图片描述

多态性是对象多种表现形式的体现。
现实中,比如我们按下F1键这个动作:

如果当前在Flash界面下弹出的就是AS 3的帮助文档;

如果当前在Word下弹出的就是Word帮助;

在Windows下弹出的就是Windows帮助和支持。

同一个事件发生在不同的对象上会产生不同的结果。

多态的实现条件
多态的三个条件:

继承的存在(继承是多态的基础,没有继承就没有多态);

子类重写父类的方法(多态下调用子类重写的方法);

父类引用变量指向子类对象(子类到父类的类型转换)。

子类转换成父类时的规则:

将一个父类的引用指向一个子类的对象,称为向上转型(upcasting),自动进行类型转换。此时通过父类引用调用的方法是子类覆盖或继承父类的方法,不是父类的方法。 此时通过父类引用变量无法调用子类特有的方法;

如果父类要调用子类的特有方法就得将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,此时必须进行强制类型转换。

以下是一个多态实例的演示,详细说明请看注释:

public class TestAnimalDemo {
    public static void main(String[] args) {
        show(new Cat()); // 以 Cat 对象调用 show 方法
        show(new Dog()); // 以 Dog 对象调用 show 方法
        Animal a = new Cat(); // 向上转型
        a.eat(); // 调用的是 Cat 的 eat
        Cat c = (Cat) a; // 向下转型
        c.work(); // 调用的是 Cat 的 work
    }
    public static void show(Animal a) {
        a.eat();
        // 类型判断
        if (a instanceof Cat) { // 猫做的事情
            Cat c = (Cat) a;
            c.work();
        } else if (a instanceof Dog) { // 狗做的事情
            Dog c = (Dog) a;
            c.work();
        }
    }
}
abstract class Animal {
    abstract void eat();
}
class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼");
    }
    public void work() {
        System.out.println("抓老鼠");
    }
}
class Dog extends Animal {
    public void eat() {
        System.out.println("吃骨头");
    }
    public void work() {
        System.out.println("看家");
    }
}

输出结果:

吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠

可以用 instanceof 判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。instanceof 的语法格式为:

对象 instanceof 类(或接口)
它的返回值是布尔型的,或真(true)、或假(false)。
#####多态的实现形式
在Java中有两种形式可以实现多态:继承和接口。

基于继承实现的多态
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。

基于继承实现的多态可以总结如下:对于引用子类的父类类型,在处理该引用时,它适用于继承该父类的所有子类,子类对象的不同,对方法的实现也就不同,执行相同动作产生的行为也就不同。

如果父类是抽象类,那么子类必须要实现父类中所有的抽象方法,这样该父类所有的子类一定存在统一的对外接口,但其内部的具体实现可以各异。这样我们就可以使用顶层类提供的统一接口来处理该层次的方法。

基于接口实现的多态
继承是通过重写父类的同一方法的几个不同子类来体现的,那么就可能是通过实现接口并覆盖接口中同一方法的几不同的类体现的。

在接口的多态中,指向接口的引用必须是指定实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。

继承都是单继承,只能为一组相关的类提供一致的服务接口。但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。

编程要求
根据提示,在右侧编辑器补充代码:

声明一个Animal类,此类中定义eat()方法;

声明Dog类、Cat类、Lion类,均继承自Animal类,并复写了eat()方法;

运用多态方式实例化子类对象并调用eat()方法打印输出信息;

具体输出要求请看测试说明。

测试说明
测试输入:无
预期输出:

eating bread...
eating rat...
eating meat...

代码实现

package case8;
public class TestPolymorphism {
	public static void main(String[] args) {
		// 以多态方式分别实例化子类对象并调用eat()方法
		/********* begin *********/
           Animal a=new Dog();
		   a.eat();
		   Animal b=new Cat();
		   b.eat();
		   Animal c=new Lion();
		   c.eat();
		/********* end *********/
	}
}
// Animal类中定义eat()方法
  abstract class Animal {
	/********* begin *********/
     abstract void eat();
	/********* end *********/
}
// Dog类继承Animal类 复写eat()方法
class Dog extends Animal {
	/********* begin *********/
      public void eat(){
		  System.out.println("eating bread...");
	  }
	/********* end *********/
}
// Cat类继承Animal类 复写eat()方法
class Cat extends Animal {
	/********* begin *********/
   public void eat(){
	   System.out.println("eating rat...");
   }
	/********* end *********/
}
// Lion类继承Animal类 复写eat()方法
class Lion extends Animal {
	/********* begin *********/
   public void eat(){
	   System.out.println("eating meat...");
   }
	/********* end *********/
}
Java头歌 3.1 封装、继承和多态 封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。本关任务:掌握继承的基本概念以及怎么使用继承。抽象类的定义规则:抽象类和抽象方法都必须用abstract关键字来修饰;抽象类不能被实例化,也就是不能用new关键字去产生对象;抽象方法只需声明,而不需实现;含有抽象方法的类必须被声明为抽象类,抽象类的子类必须复写所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。抽象类的定义格式:abstract class 类名称 // 定义抽象类声明数据成员; 阅读详情

相关推荐

Java头歌4.2 类的封装、继承、多态(含抽象类、接口知识)

本关任务:按要求编写一个Java应用程序,巩固Java面向对象知识。

weixin_74284876的博客 5015

java封装,继承和多态

1 package case8; public class TestPolymorphism { public static void main(String[] args) { // 以多态方式分别实例化子类对象并调用eat()方法 /********* begin *********/ Animal a=new Cat(); Animal b=new Dog(); Animal c...

NJU phd 在读。 3115

继承和多态

Java面向对象编程的三大范式,封装,继承,多态,对初学者学习Java,认识Java提供了很好的参考

Java学习——面向对象(封装)

封装 一、定义 一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其它对象就可以完成自己的操作。 封装就是把一个对象的属性私有化,同时提供一些可以被外界访问属性的方法。封装的关键就是绝不能让类中的方法直接访问其他类的数据(属性),程序仅通过对的方法与对象的数据进行交互。 二、封装的三大好处(安全性,复用性,简单化) 良好的封装能减少耦合; 类内部的结构可以自由修改; 可以对成员变量更精确的控制,隐藏信息(1,0),实现等细节(if age>50); 三、private关键字 1、概念 私有的,一

qq_42286362的博客 1326

Uibot RPA中级认证实战:手把手教你用流程创造者搞定客户数据迁移(附验证码容错技巧)

本文详细介绍了Uibot RPA中级认证实战中的客户数据迁移工程化解决方案,特别针对验证码容错技巧和动态表格处理等核心挑战。通过环境准备、登录模块设计、数据提取技术及容错体系的系统讲解,帮助RPA实施工程师掌握高效稳定的自动化流程开发方法,提升企业数据迁移效率。

weixin_30505225的博客 229

Vivado时序违例debug

显示了数据路径延迟。例如,对于违例路径,若布线延迟超过50%,说明该延迟是导致时序不能收敛的主要因素,因此可围绕降低布线延迟这一靶心达到时序收敛。对于跨时钟域路径,Requirement数值会有所变化,但如果数值为0.1,显然是不合理的。目的时钟路径单元,时钟从adc0_bufg/O输出,到达PLLE4_ADV,经过BUFGCE输出,最终到达SRLC32E移位寄存器,对应。源时钟路径单元,时钟从adc0_bufg/O输出,到达PLLE4_ADV,经过BUFGCE输出,最终到达FDRE触发器,对应。

weixin_44513618的博客 1621

十三、java类的封装、继承、多态

面向对象的三个基本特性就是:封装、继承和多态。 前面讲解了java 程序都是由类文件组成的,java是面向对象的程序设计语言,在java中面向对象的思想就是由类的设计来体现的,也即类的继承、封装和多态。   一、封装(encapsulation) 封装性就是把类(对象)的属性和行为结合成一个独立的相同单位,并尽可能隐蔽类(对象)的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部

liujun13579的专栏 6853

抓包网络调试工具 reqable抓包教程

如果CA根证书未安装成功,网络图标是黄色,点击盾牌图标可以进入CA根证书安装界面,详细步骤请阅读。在API调试中,获取流量是第一步也是最基本的操作,这里讲解下如何使用Reqable获取流量,通俗地讲就是抓包。我们可以选择一个图片请求,双击打开详情面板,能够看到该请求的详细信息。如果系统代理未设置,网络图标是黄色,点击网络图标可以自动设置系统代理。此域名的结构树,可以查看该域名下所有请求的目录结构,点击选择可以查看该请求的详情。首先,需要启用Reqable的调试功能,点击最右上角的。打开浏览器,输入地址。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2562

第十三章 封装、继承、多态

第十三章 封装、继承、多态 封装(提高数据的安全性) 将数据(属性)和行为(方法)包装到类对象中,在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的实现细节,从而将问题简化。 在python中没有专门的修饰符用于属性的私有,如果不希望该属性在类的外部被使用,可以在前面加两个"_"。 可以使用_类名__变量名访问私有属性(尽量不要使用这种方法) class Student: def __init__(self,name,age): self.name = n

qq_42385761的博客 213

Claude Code(7):从零创建你的第一个 Skill

在前面的文章,我们介绍了 Skills 的基本概念,这篇我们深入实战,从零开始创建你的第一个 Skill,并逐步解锁所有配置项,让 Claude Code 真正熟悉你的测试规范和习惯。

blues_C的博客 649

51单片机计算器(源程序+流程图+答辩报告+综合设计)

保姆级讲解!C语言编程,使用51单片机及LCD1602显示屏实现!

m0_57007304的博客 2万+

python语言基础(十三)面向对象编程(封装、继承、多态)

面向对象的三大特征:封装、继承、多态。 封装 封装是面向对象编程的一大特点,将属性和方法放到类的内部,通过对象访问属性或者方法,隐藏功能的实现细节,也可以设置访问权限。 class Student(): def __init__(self,name,age): self.name = name # 将属性封装到类的内部 self.age = age def prin_info(self): print(self.name,self.ag

hwwaizs的博客 855

【2023校招】网易雷火_研发岗_笔试题解

几个月没写题,果然水平不在线了hh,AK更难实现喽,当天只AK了疯狂游戏; 题目描述和数据等尽量多的CV到了DEVC里,可能不够细节和准确; 下面进入正题,分享我们此次笔试的题目描述和代码设计吧~.........

米莱虾 4544

Python:十三、封装、继承、多态,类方法和静态方法,类中常用魔术方法,单例设计模式

一、封装 概念:一个类的某些属性,在使用的过程 中,不希望被外界直接访问,而是把这个属性给作为私有的【只有当前类持有】,然后暴露给外界一个访问的方法即可【间接访问属性】 封装的本质:就是属性私有化的过程 封装的好处:提高了数据的安全性,提高了数据的复用性 面向对象的特征:封装、继承、多态 1.1 属性私有化 如果想让成员变量不被外界直接访问,则可以在属性名称的前面添加两个下划线__(不能双下划线结尾的属性).成员变量则被称为私有成员变量 私有属性的特点:只能在类的内部通过函数方法直接被

weixin_44180787的博客 301

100天精通Python(基础篇)——第3天:运算符全解析(算术运算符、比较运算符、逻辑运算符、赋值运算符及其优先级规则)

100天精通Python(基础篇)——第3天:运算符全解析(算术运算符、比较运算符、逻辑运算符、赋值运算符及其优先级规则)

努力让自己发光,对的人才能迎着光而来 14万+

操作系统实验四 进程运行轨迹的跟踪与统计(哈工大李治军)

实验4 进程运行轨迹的跟踪与统计 实验目的 掌握 Linux 下的多进程编程技术; 通过对进程运行轨迹的跟踪来形象化进程的概念; 在进程运行轨迹跟踪的基础上进行相应的数据统计,从而能对进程调度算法进行实际的量化评价,更进一步加深对调度和调度算法的理解,获得能在实际操作系统上对调度算法进行实验数据对比的直接经验。 实验内容 进程从创建(Linux 下调用 fork())到结束的整个过程就是进程的生命期,进程在其生命期中的运行轨迹实际上就表现为进程状态的多次切换,如进程创建以后会成为就绪态;当该进程被调度以

leoabcd12的博客 4654

C# 十三、理解:封装、继承、多态、值和引用类型、抽象类、接口、委托、重写和重载

1.封装 理解:将类里面的成员变量和方法私有化,如果外界要访问,向外界提出一个统一访问的方法。 (对成员变量的封装,对方法的封装) 好处:减少耦合,防止外界修改。 实现方式: (1)编写Public方法进行私有变量或方法的封装。 (2)属性。 2.继承 理解:创建新的类(派生类/子类),可以继承现有类(基类/父类)的特性,并且还可以进行修改和扩充。 父类访问修饰符: ...

qq_43610722的博客 557

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

第十三周 5.27面向对象的三大特性(封装、继承、多态)(三)

面向对象的三大特性(封装、继承、多态)instanceof避免类型转换异常知识点及多态的应用

2302_81787841的博客 382

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

第十三周任务 项目5-银行系统

/* * Copyright (c) 2012, 烟台大学计算机学院 * All rights reserved. * 作 者:张中华 * 完成日期:2012 年 11月 25日 * 版 本 号:v1.0 * 输入描述:银行密码 * 问题描述:无 * 程序输出:略 * 问题分析:略 *算法设计:略 */#include

zzh 420

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java基础(八):封装、继承、多态性

从类的定义来看,类是一类具有相同特性的事物的抽象描述。而实例变量和实例方法就是事物的特征,那么父类中声明的实例变量和实例方法代表子类事物也有这个特征。如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有空参的构造器,则。所以继承意味着子类的对象除了看子类的类模板还要看父类的类模板。问题:在创建子类对象的过程中,一定会调用父类中的构造器吗?一个引用类型变量可能指向(引用)多种不同类型的对象。特别说明:应该避免子类声明和父类重名的成员变量。问题:创建子类的对象时,内存中到底有几个对象?

从基础到源码解析的学习记录 2983

十三 继承和多态

十三 继承和多态 1、继承 ▶继承:是面向三大对象特性之一,通过继承我们可以使用一个类获取到其它类中的属性和方法。 ▶在定义类的时,可以在类名后面的括号中指定当前类的父类(超类、基类)。 ▶继承的作用: 1.提高了代码的复用性; 2.让类与类之间产生了关系。有了这个关系,才有多态的特性。 class Person(): name=' ' age=' ' class Doctor(): name=' ' age=' ' def study(self

weixin_44864954的博客 177

Python面向对象编程:数据封装、继承和多态

点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达小编的 Python 学习之路颇不顺畅,平日里不大会合理安排时间,东一榔头西一钉耙的学习方法怕是不能久远,看别人是 Python从入门到精通,估计小编再这样下去是要从入门到放弃了。昨日在某个 R 语言学习群里听到某圈友说吴喜之老先生都 70 多岁了还在学习 Python,前几日又从另外一个圈子听到某位朋...

小白学视觉 820

Javascript(五十三)面向对象的多态和继承

面向对象,继承、封装、多态。 面向对象是一个编程思想,支撑面向对象编程思想的语法是类(ES6之前没有这个概念)和对象。构造函数充当类的角色。构造函数和对象实现面向对象程序的时候,体现封装,继承,多态的特点。 封装:封构造函数 继承 继承:分类更加细分的构造函数 1.继承父一级的所有属性(改变父级构造函数的this指向) Teddy无法直接继承Dog的原型对象,也就无法调用Dog的方法。因为本身不是通过new创建的Teddy,Teddy的也就无法直接共享到父一级上的方法。 2.继承父一级的原型对象(方法)

weixin_44730244的博客 212

复习 Java类和对象、继承多态、抽象类接口

类和对象、继承多态、抽象类接口一、面向对象三大特征二、final关键字三、static关键字四、设计模式-单例模式懒汉模式饿汉模式全局锁式静态代码块双重锁模式静态内部类五、访问限定符六、多态的实现原理七、重载和重写的区别八、抽象类和接口的区别1.抽象类:2.接口九、异常1.常见异常理解2.继承结构Object3.异常处理机制十、Object类方法十一、类加载过程1.装载阶段2.连接阶段3.初始化阶段十二、反射1.拿到当前类的class对象2.通过class对象获取构造方法,生成当前类3.通过class对..

qq_48319882的博客 1495

封装和继承

一、封装 面向对象的三大特征:封装性 当创建完对象以后,如果直接通过“对象名.属性名”的方式给属性赋值的话,可能会出现一些不符合实际情况的问题,所以我们不考虑使用“对象名.属性名”的方式赋值,而是通过“对象名.方法名()”的方法进行赋值,因为可以在方法里加上大量的业务逻辑,对属性值进行限制 解决方法: 1.将属性私有化 2.提供公用的(get and set)方法实现属性的取值和赋值 二、在我们去创建对象的时候,会用到一个特殊的方法,构造器 怎么去创建一个构造方法? Public 构造方法名(形参){ }

turbofang_的博客 199

Delphi封装,继承,多态,接口,命令统计

delphi类常用命令

weixin_46297949的博客 428
上一篇: 十二、类与对象
下一篇: 十四、封装、继承和多态的综合联系
请你吃茶去
博客等级 码龄6年 704粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请你吃茶去

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值