大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。
当前系列: J&C 修改讲义

构造函数

复习:面向对象:类成员:构造函数 / 属性 / 析构(垃圾回收) 

参数重载

即一个类中可以有多个参数不同的构造函数,如下所示:

    class Student
    {
        public Student(String name){}
        public Student(String name, int age){}
    }

调用的时候,按方法重载规则进行匹配。

同时你会发现再也不能使用new Student()调用无参的构造函数了。这是因为:一旦声明了任何构造函数,之前默认自带的隐式的(implicit)无参构造函数消失。

如果你还想保留无参构造函数,需要在类中显式(explicit)的声明。

    class Student
    {
        public Student() {}


内部类

在一个类的内部声明的类被称之为内部类。

内部类和外部类之间可以互相访问(即使是private的)。

class Student
{
	private void learn() {
		new Score().add();
	}
	
	class Score{
		private void add() {
			new Student().learn();
		}
	}
}
但是,
  • 外部无法访问内部类:
    //		new Student().Score 没有这种写法
  • 除非内部类是静态的:
    class Student
    {
    	/* private */ static class Score{
    Student.Score ss = new Student.Score();    //此时Score不能被private修饰


继承

复习:面向对象:继承 / protected / 父类装子类 / 类型转换 / 滥用

继承为类的实例化带来了一个问题:

实例化一个子类,需要首先调用它(全部的,即包含祖先的)父类构造函数。因为父类成员的存在,必须是在类的实例化之后(任何类都一样,你要使用这个类的实例成员,当然要先对这个类实例化一次——实例化就必须通过调用构造函数实现)。

子类默认会调用父类的无参构造函数。

断点演示:显式声明/隐藏无参构造

class Person 
{
	public Person() {	//断点自动击中;如果被隐藏,会报编译错误
	}
	
	public Person(int age) {
	}
}

但是,如果父类没有无参构造函数,就需要在子类的构造函数中指定具体调用父类的哪一个构造函数:

class Student extends Person {
	public Student() {
		super(18);  //对应this()
	}
}

演示:再添加一个基类:

class Entity{
class Student extends Person {

new Student()时要从Entity的构造函数开始。

C#使用base关键字

不允许被继承

复习:面向对象:继承 / protected / 父类装子类 / 类型转换 / 滥用

Java中的关键字是final(和常量关键字相同,意思是不变了),C#中关键字是sealed(封闭的)

演示:

  • 标记某个类不能再被继承:
    final class Person {
  • 标记某个方法不能再被override
    public final void Eat() {


抽象类和抽象方法

由abstract定义的方法叫做抽象方法,抽象方法不能有方法体({}都不能有,空的也不行),只能放置在被abstract修饰的抽象类中。

    //要在类中声明abstract方法,类上就必须加abstract
    abstract class Person
    {
        //abstract修饰的方法不能有方法体!
        public abstract void Eat();
    }

抽象类有一个非常明显的特点:能被实例化!

new Person();  //报错
能实例化的是它的子类:
new Student();    //OK
class Student extends Person {

注意抽象方法的子类必须实现抽象方法里面的全部抽象方法:(所以抽象方法也不能private)

因为抽象方法没有方法体,所以子类也不能通过base调用其父类的抽象方法。



接口(interface)

由interface关键字声明的……和类极其类似的那玩意儿……叫做接口:

interface IMove {    //C#中接口惯例加“I”作为前缀(Java没有)

接口和抽象类非常类似。

抽象方法也可以放在接口中:

interface IMove {
	void Walk();
	int Run(int miles);
}

接口一样不能实例化。

接口一样可以被“继承”,但我们将其称之为“实现(implement)”,子类实现接口用的关键字是implements(但C#中仍然使用冒号(:))

class Teacher implements IMove {

接口的子类,都必须实现接口中定义的全部抽象方法。(演示:F2 auto fix自动生成)

一个类可以同时继承基类并实现(多个)接口,比如:

,同时继承和实现


接口 vs 抽象类

常见面试题:接口和抽象类有什么区别?

注意首先声明:所谓接口,是传统意义上的接口。

最简单的回答是从语法层面来说,比如:(演示:)


抽象类
接口
非抽象方法 可以有(@想一想@:为什么,有啥用?) 不能有
构造函数 可以有 不能有
子类可继承/实现 一个 多个
普通字段(@想一想@:属性呢?) 可以有 不能有(新版本才可以有条件的有……)
相互间 可以实现接口 不能继承抽象类
访问修饰符 可以protected 默认/只能public

但实际上,因为面向对象是代码管理的工具,我们更应该透过语法探究其所需要表达的意义:

抽象类还是一个类,类通常都被认为是对现实中事物的映射,是对事物的行为和状态的抽象。所以,类名一般都是名词(比如Person、Animal、Major之类的),既有行为(方法)也有状态(字段),其中:

  • 普通基类,映射的是实体(entity,可简单理解为:实际存在的物体),实体就可以有自己独立的行为
  • 抽象类,映射的是非实体的、抽象的概念,概念首先没法实例化,然后也没有具体的行为
比如:如果已律师、包工头、码农做子类,这些子类对象都可以挣钱;但抽象出来的职业,如何挣钱就比较尴尬了,职业能挣钱,但具体怎么挣呢?

你真要完成挣钱这事,还得依赖具体的实例:

Career career = new Career();    //怪异,这职业究竟是啥职业?
Career career = new Layer();     //OK了,律师这种职业对象,不错
接口从语法角度,interface也是一种class
IMove atai = new Student();    //父类变量装子类对象
但它通常被认为是对行为(没有状态)的抽象,所以接口名一般都是动词(比如IMove、ILearn),映射的是一些操作,其中只有方法(属性本质上也是一种方法)。

最后,相较于普遍基类,抽象类和接口是一种更纯粹的抽象。纯粹度:接口 > 抽象类 > 普通父类

所谓API

即应用接口(application interface)。

是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。

说人话:应用程序对外部提供的一系列抽象方法/方法定义(即:不带方法体部分),外部可以:

  • 通过调用这些方法获得相应的结果,或者
  • 实现/override这些方法,自定义应用程序

理解接口,最好的例子:usb接口

  • 首先体现的是一种协议:插头和插孔都要按固定的标准做
  • 然后,接口可以输出一些东西,比如电流,至少你可以用usb接口充电
  • 最后,你可以扩展这个接口,比如:装摄像头、麦克风,把数据输入给电脑

但注意:接口本身不实现任何东西。


现代接口

复习:面向对象:多态:override / 为什么 / 抽象类 / 接口

Java 8 / C# 8.0,从时间上看,是C#模仿的Java。

默认方法

居然可以在接口中出现方法体/实现了:

default void Walk() {
	System.out.println("迈着六亲不认的步伐");
}
但是,注意:
  • 前面要加default修饰符,这种方法被称之为默认虚拟方法。(C#中连default修饰都不需要
  • 访问修饰符要么默认,要么就显式public,不能protected/private啥的

实现类对象可以直接调用接口中的默认方法:

new Person().Walk();

静态方法/字段

接口中还可以有静态方法:

static double getSpeed() {
	return 98.6;
}

一样不能private/protected啥的。

以及静态常量字段:
public static final double speed = 70;

public、static和final都可以省略,因为是默认且不可更改的

接口中的静态方法通常用于default方法中:

default void Walk() {
	System.out.println("迈着六亲不认的步伐,速度" + getSpeed());
}


作业

  1. 设计一种方式,保证每一个User对象一定有Name和Password赋值
  2. 让User类无法被继承。
  3. 用最简单/优雅的方法,让:
    • Problem类可以在生成其对象时设定悬赏值。
    • 所有Entity(及其子类)对象生成时,就能获得一个(累加的不重复)id
    • 每一个Content对象一定有Body赋值
  4. 声明一个令牌管理(TokenManager)类,利用之前学过的位运算
    1. 使用私有的_tokens字段存储所具有的权限
    2. 暴露Add(Token)、Remove(Token)和Has(Token)方法,可以添加、删除和判断其有无某个权限
    3. TokenManager是用于存储用户权限的,它怎么和User类关联呢?
  5. 定义一个仓库(Repoistory)类,用于(模拟)存取对象,其中包含:
    1. 一个int类型的常量version
    2. 思考Respoitory应该是static类还是实例类更好
    3. 将Repoistory作为属性放入求助(Problem)中,静态好,还是实例好?
  6. 设计一个类FactoryContext,保证整个程序运行过程中,无论如何,外部只能获得它的唯一的一个实例化对象。(提示:设计模式之单例)
  7. 引入Message的两个子类EmailMessage和DBMessage,并让他们实现接口ISendMessage(其中含Send()方法声明):
    • EmailMessage.Send():控制台输出“send by email……”
    • DBMessage.Send():控制台输出“send by database……”
  8. 如果一定要对之前的Content类再进行抽象,应该将其改成抽象类还是接口?为什么?并按你的想法实现。
  9. 一起帮里的求助总结(Summary,注意是求助Problem)、文章和意见建议,以及他们的评论,都有一个点赞(Agree)/踩(Disagree)的功能,赞和踩都会增减作者及评价者的帮帮点。能不能对其进行抽象?如何实现?
  10. 一起帮还可以在好友间发私信,所有又有了IChat接口,其中也有一个Send()方法(之前的Send()方法)声明。假设User类同时继承了ISendMessage和IChat,如何处理?

---------- 在学习完 JavaC#类库后完成 ----------

  1. 观察一起帮登录页面,用if...else...完成以下功能。
    用户依次由控制台输入:验证码、用户名和密码:
    • 如果验证码输入错误,直接输出:“* 验证码错误”;
    • 如果用户名不存在,直接输出:“* 用户名不存在”
    • 如果用户名或密码错误,输出:“* 用户名或密码错误”
    • 以上全部正确无误,输出:“恭喜!登录成功!”
    PS:验证码/用户名/密码直接预设在源代码中,输入由控制台完成。
  2. 定义方法getRandom(),生成一个元素值随机,但从小到大排列的数组。通过参数控制
    • 最小值/起始值(默认为0)
    • 相邻元素间最大差值(默认为10)
    • 元素个数(没有默认值
  3. 修改之前的GetAverage(),用户(调用方)能够要求返回的平均值:
    • 向上/向下取整,
    • 四舍五入保留若干位小数(默认,2位)
    2和3都要能利用方法重载优化。
  4. 定义一个类RandomArray,包含一个方法get(),能够通过:
    1. 构造函数传参
    2. 属性设值
    的方式,实现和第2题一样的功能
  5. 完成“猜数字”游戏,方法名GuessMe():
    • 随机生成一个大于0小于1000的整数
    • 用户输入一个猜测值,系统进行判断,告知用户猜测的数是“大了”,还是“小了”
    • 没猜中可以继续猜,但最多不能超过10次
      • 如果5次之内猜中,输出:你真牛逼!
      • 如果8次之内猜中,输出:不错嘛!
      • 10次还没猜中,输出:(~ ̄(OO) ̄)ブ


学习笔记
源栈学历
键盘敲烂,月薪过万作业不做,等于没学

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 J&C 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码