不能取得类pictrure的insert属性_typescript 07-类

7f2472e8d943da2ab9341a5dd5781804.png

知识导向

  • 基础
  • 修饰符
  • readonly修饰符
  • 参数属性
  • 静态属性
  • 可选属性
  • 存取器
  • 抽象类
  • 实例类型
  • 前面章节有关于类的补充

基础

定义类使用class关键字

class Point {

    public x: number
    public y: number

    constructor(x: number, y: number){
        this.x = x
        this.y = y
    }

    public getPosition(){

        return `(${this.x},${this.y})`
    }
}

const point = new Point(1,2)
console.log(point);

// 结果 Point { x: 1, y: 2 }

这里我们定义了一个叫Point的类,这个类里面包含了x,y两个属性,一个构造函数(constructor方法就构造函数)和一个getPosition方法 。

我们在引用任何一个类成员的时候都用了this。 它表示我们访问的是类的成员。

最后一行,我们使用new构造了Point类的一个实例。 它会调用之前定义的构造函数,创建一个ponint类型的新对象,并执行构造函数初始化它。

继承

在TypeScript里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。

// 父类/基类
class Parent {
    
    public name: string

    constructor(name: string) {
        this.name = name
        console.log(this.name);
        
    }
}

// 子类/派生类
class Child extends Parent {

    constructor(name: string) {
        super(name)
    }
}

const child = new Child('cyang')
//结果 cyang

这个例子展示了最基本的继承:类从基类中继承了属性和方法。这里,Child是一个派生类,它派生自Parent基类,通过extends关键字。 派生类通常被称作子类,基类通常被称作超类或父类

派生类包含了一个构造函数,它必须调用super(),它会执行基类的构造函数。 而且,在构造函数里访问this的属性之前,我们一定要调用super()。 这个是TypeScript强制执行的一条重要规则。

修饰符

公共public,私有private受保护的修饰符protected

公共的 public (都可访问)

公共的,你可以将成员明确的标记为puclic

私有的private (只能在类中访问)

当成员被标记成private时,它就不能在声明它的类的外部访问。

class Parent {

    private age: number

    constructor(age: number) {
        this.age = age
    }
}

const p = new Parent(18)

console.log(p.age);//error 属性“age”为私有属性,只能在类“Parent”中访问。

这里的age是一个私有的属性,只能在类里面读取访问。

同样,在派生类中也一样不能访问。

class Child extends Parent {

    constructor(age: number) {
        super(age)
        console.log(super.age);//error 通过 "super" 关键字只能访问基类的公共方法和受保护方法。
        console.log(this.age);//error 属性“age”为私有属性,只能在类“Parent”中访问。
    }
}

受保护的protected (在类和子类中访问)

protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。

例如:

class Parent {

    protected age: number

    constructor(age: number) {
        this.age = age
    }

    protected getAge() {

        return this.age
    }
}

class Child extends Parent {

    constructor(age: number) {
        super(age)
        console.log(super.age);//error 通过 "super" 关键字只能访问基类的公共方法和受保护方法。
        console.log(super.getAge());
        //结果 18
    }

    public getParent() {

        return `${this.age}`
    }
}

const child = new Child(18)
console.log(child.getParent());
//结果 18

注意,我们不能在Parent类外使用age,但是我们仍然可以通过Child 类的实例方法访问,因为Child 是由Parent派生而来的。

构造函数也可以被标记成protected。这意味着这个类不能在包含它的类外被实例化,但是能被继承。比如,

class Parent {

    private age: number

    protected constructor(age: number) {
        this.age = age
    }
}

class Child extends Parent {
    
    constructor(age: number) {
        super(age)
    }
}

const p = new Parent(18)//error 类“Parent”的构造函数是受保护的,仅可在类声明中访问。
const c = new Child(18)

readonly修饰符(只读)

你可以使用readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。

class UserInfo {

    public readonly name: string

    constructor(name: string){
        this.name = name
    }
}

const userinfo = new UserInfo('cyang')

userinfo.name = 'yangc'//error Cannot assign to 'name' because it is a read-only property.意思是这个属性是只读的,不可修改

参数属性

参数属性通过给构造函数参数前面添加一个访问限定符来声明。 使用public限定一个参数属性会声明并初始化一个私有成员;对于privateprotectedreadonly来说也是一样。

class Params {

    constructor(public name: string) {}
}

const params = new Params('cyang')

console.log(params.name);

静态属性

我们也可以创建类的静态成员,这些属性存在于类本身上面而不是类的实例上。

class Parent {

    public static age: number = 18

    constructor() {}

    public static getAge() {

        return Parent.age
    }
}

const p = new Parent()

console.log(p.age);//error Property 'age' is a static member of type 'Parent'.意思是这个成员是静态的,只能通过Parent类访问
console.log(Parent.age);
//结果 18

可选属性?

有些属性可传可不传,这时候,我们可以使用可选属性来定义它。

class Info {

    public name: string
    public age?: number

    constructor(name: string, age?: number, public sex?: string) {
        this.name = name
        this.age = age
    }
}

const info1 = new Info('cyang')
console.log(info1);
//结果 Info  {sex: undefined, name: "cyang", age: undefined}

const info2 = new Info('cyang', 18)
console.log(info2);
//结果 Info {sex: undefined, name: "cyang", age: 18}

const info3 = new Info('cyang', 18, '男')
console.log(info3);
//结果 Info {sex: "男", name: "cyang", age: 18}

这里我们定义了属性、可选属性和可选参数属性。

存取器

TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问

get: 在获取值时调用的方法

set:在设置值时调用的方法

class Parent {

    public name: string
    public age?: number
    private _GET: String

    constructor(name: string, age?: number) {
        this.name = name
        this.age = age
        this._GET = `这是需要取的值, ${this.name} ${this.age? `,${this.age}`: ''}`//可选参数的判断
    }

    get getTter() {

        return this._GET
    }

    set setTter(value: string) {

        console.log(value);
        this._GET = value
    }
}

const p = new Parent('cyang',18)

console.log(p.getTter);
//取值结果 这是需要取的值, cyang 

console.log(p.name = 'yangc');
// 赋值结果 yangc

对于存取器有下面几点需要注意的:

首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。 其次,只带有 get不带有 set的存取器自动被推断为 readonly。 这在从代码生成 .d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。

抽象类

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

abstract class People {

    constructor(public name: string) {}

    public abstract printName(): void
}

const p = new People()//error 无法创建抽象类的实例。

抽象类不能被实例化。

抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含abstract关键字并且可以包含访问修饰符。

abstract class People {

    constructor(public name: string) {}

    public abstract printName(): void
}

// const p = new People()//error 无法创建抽象类的实例。

class Man extends People {

    constructor(name: string) {
        super(name)
        this.name = name
    }

    printName() {
        
        console.log(this.name);
    }
}

const m = new Man('cyang')

m.printName()
//打印出 cyang

实例类型

当你在TypeScript里声明了一个类的时候,实际上同时声明了很多东西。 首先就是类的实例的类型。

class Greeter {

    public greeting: string

    constructor(message: string) {
        this.greeting = message;
    }

    public greet() {

        return "Hello, " + this.greeting;
    }
}

let greeter: Greeter = new Greeter("world");

console.log(greeter.greet());
//结果 Hello,world

这里,我们写了let greeter: Greeter,意思是Greeter类的实例的类型是Greeter

我们也创建了一个叫做构造函数的值。 这个函数会在我们使用new创建类实例的时候被调用。

前面章节有关于类的补充

我们也可以把类当作接口使用:

class Point {
    x: number;
    y: number;
}

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};

泛型在类中的使用:

const create = <T>(c: new() => T): T => {

    console.log(c);
//结果 Infos() {
//        this.age = 18;
//    }
    return new c()
}
class Infos {

    public age: number

    constructor() {
        this.age = 18
    }
}

console.log(create<Infos>(Infos));
//结果 Parent{ age: 18 }

console.log(create<Infos>(Infos).age);
//结果 18

这里使用Infos类作为泛型变量、参数的返回值类型和方法的返回值类型,new() => T这个方法作为参数的类型,这里的create是一个方法。

比较绕需多加动手操作,打印出不同的参数理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值