目录
前言
对tyscript的类,构造函数,继承,super,抽象类,属性的封装,接口,泛型等进行了学习
类的简介
//使用class关键字来定义一个类
/*
对象中主要包含了两个部分:
属性
方法
*/
class Person{
/*
直接定义的属型是实例属性,需要通过对象的实例去访问;
const per=new Person();
per.name
使用static开头的属性时静态属性(类属性)。可以直接通过类去访问
Person.age
readonly开头的属性表示一个只读的属性无法修改
*/
//定义实例属性
name:string="孙悟空";
//static name:string="猪八戒";
//在属性前使用static关键字可以定义类属性(静态属性)
static age:number=18;
//static readonly age:number=19;//注意static和readonly的顺序
age2=18;
/*
如果方法以static开头就是类方法,可以直接通过类去调用
*/
//定义实例方法
sayhello(){
console.log("hello,大家好");
}
//类方法
static sayhello(){
console.log("hello,大家好");
}
}
const per=new Person();
console.log(per);
//console.log(per.name,per.age);//报错,因为age是静态属性
console.log(Person.age);
console.log(per.name);
per.name="tom";
console.log(per.name);//实例属性可读可改,若属性前加上readonly则不能修改属性值
per.sayhello();
Person.sayhello();
构造函数
class Dog{
//在类里面定义属性
name:string;
age:number;
//constructor被称为构造函数
//构造函数会在对象创造时调用
constructor(name:string,age:number){
//在实例方法中,this就表示相当于当前的实例
//在构造函数中当前对象就是当前新建的那个对象
//可以通过this向新建的对象中添加属性
//在构造函数里面传参
console.log("构造函数执行了~~");
console.log(this);
this.name="name";
this.age=age;
}
bark(){
//alert("汪汪汪");
//在方法中可以通过this来表示当前调用方法的对象
console.log(this);
}
}
const dog=new Dog("小黑",4);
const dog2=new Dog("小白",2);
//console.log(dog);
//console.log(dog2);
dog.bark();
dog2.bark();
继承
(function(){
//定义一个animal类
class Animal{
name:string;
age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
}
sayHello(){
console.log("动物在叫~");
}
}
//定义一个表示狗的类
// class Dog{
// name:string;
// age:number;
// constructor(name:string,age:number){
// this.name=name;
// this.age=age;
// }
// sayHello(){
// console.log("汪汪汪");
// }
// }
//定义一个表示猫的类
// class Cat{
// name:string;
// age:number;
// constructor(name:string,age:number){
// this.name=name;
// this.age=age;
// }
// sayHello(){
// console.log("喵喵喵");
// }
// }
// const dog=new Dog("旺财",5);
// console.log(dog);
// dog.sayHello();
// const cat=new Cat("咪咪",3);
// console.log(cat);
// cat.sayHello();
/*
Dog extends Animal
此时,Animal被称为父类,Dog被称为子类
使用继承后,子类会拥有父类所有的方法和属性
通过继承可以将多个类中共有的代码写在一个父类中
这样主需要写一次即可让所有的子类都同时拥有父类中的属性和方法
如果希望在子类中添加一些父类中没有的属性或方法直接加到子类中即可
如果在子类中添加了和父类相同的方法,则子类方法会覆盖父类的方法
这种子类覆盖掉父类方法的形式,我们称为方法的重写
*/
//使Dog类继承Animal类
class Dog extends Animal{
run(){
console.log(`${this.name}在跑`);
}
sayHello(): void {
console.log("汪汪汪");
}
}
class Cat extends Animal{
sayHello(): void {
console.log("喵喵喵");
}
}
const dog=new Dog("旺财",5);
console.log(dog);
dog.sayHello();
dog.run();
const cat=new Cat("咪咪",3);
console.log(cat);
cat.sayHello();
})();
super
(function(){
class Animal{
name:string;
constructor(name:string){
this.name=name
}
sayhello(){
console.log("动物在叫~~");
}
}
class Dog extends Animal{
age:number;
constructor(name:string,age:number){
//如果在子类中写了构造函数,在子类构造函数中必须对父类的构造函数进行调用(因为子类构造会覆盖父类的构造)。
super(name);//调用父类的构造函数
this.age=age;
}
sayhello(): void {
//在类的方法中,super就表示当前类的实例
super.sayhello();
console.log("汪汪汪");
}
}
const dog=new Dog("旺财",2);
dog.sayhello();
})();
抽象类
(function(){
/*
以abstract开头的类是抽象类
抽象类和其他类区别不大,只是不能用来创建对象(会报错)
抽象类就是专门用来给子类继承的
抽象类中可以添加抽象方法
*/
abstract class Animal{
name:string;
constructor(name:string){
this.name=name
}
//抽象方法使用abstract开头,没有方法体
//抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayhello():void;
}
class Dog extends Animal{
sayhello(): void {
//在类的方法中,super就表示当前类的实例
console.log("汪汪汪");
}
}
class Cat extends Animal{
sayhello(): void {
console.log("喵喵喵");
}
}
const dog=new Dog("旺财");
dog.sayhello();
})();
接口
(function(){
//描述一个对象的类型
type myType={
name:string,
age:number;
}
const obj:myType={
name:"sss",
age:111
}
/*
接口用来定义一个类结构 用来定义一个类中应该包含哪些属性和方法
同时接口也可以当成类型声明去使用
接口可以重复声明,所声明的所有属性加起来才是该接口声明的属性 type不允许重复声明
*/
interface myInterface{
name:string,
age:number;
}
interface myInterface{
gender:string;
}
const obj2:myInterface={
name:"sss",
age:111,
gender:"男",
}
/*
接口可以在定义类的时候去限制类的结构
接口中的所有的方法都不能有实际的值
接口只定义对象的结构,而不考虑实际值
在接口中的所有的方法都是抽象方法
*/
interface myInter{
name:string;
sayHello():void;
}
/*
定义类时,可以使类去实现一个接口
实现接口就是使类满足接口的要求
interface和abstract是ts中独有的,在js中并没有,ts文件编译后在js文件中是找不到的
*/
class Myclass implements myInter{
name: string;
constructor(name:string){
this.name=name;
}
sayHello(){
console.log("大家好");
}
}
})();
属性的封装
(function(){
//定义一个表示人的类
class Person{
//ts可以在属性前添加属性的修饰符
/*
public修饰非属性可以在任意位置访问(修改) 默认值,子类可以继承
private 私有属性,只能在类内部进行访问(修改),子类也不能继承
通过在类中添加方法使得私有属性可以被外部访问
protected 受包含的属性,只能在当前类和当前类的子类中访问
*/
name:string;
age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
}
//定义方法,用来获取name属性
getName(){
return this.name;
}
//定义方法,用来设置name属性
setName(value:string){
this.name=value;
}
getAge(){
return this.age;
}
setAge(value:number){
//判断年龄是否合法
if(value>=0){
this.age=value;
}
}
/*
getter方法用来读取属性
setter方法用来设置属性
他们被称为属性的存取器
*/
//ts中设置getter方法
get name2(){
return this.name;
}
set name2(value:string){
this.name=value;
}
get Age2(){
return this.age;
}
set Age2(value:number){
this.age=value;
}
}
const per=new Person("孙悟空",18);
console.log(per);
/*
现在属性是在对象中设置的,属性可以任意的被修改
属性可以被任意修改将会导致对象的数据变得非常不安全
*/
per.name="猪八戒";
per.age=28;
console.log(per);
console.log(per.getName());
per.setName("唐僧");
console.log(per.getName());
console.log(per.name2);//setter和getter调法跟属性的一样,但调的是方法
class A{
num:number;
constructor(num:number){
this.num=num;
}
}
class B extends A{
test(){
console.log(this.num);
}
}
const b=new B(123);
//B.num=22;报错 类外不能访问
class C{
//可以直接将属性定义在构造函数中
constructor(public name:string,public age:number){
}
}
const c=new C("旺财",12);
console.log(c);
})();
泛型
// function fn(a:number):number{
// return a;
// }
/*
在定义函数或是类型,如果遇到类型不明确就可以使用泛型,函数执行是才指定类型
*/
function fn<T>(a:T):T{
return a;
}
//可以直接调用具有泛型的函数
let result=fn(10)//不指定泛型:自动类型推断
let result2=fn<string>('hello');//指定泛型
//泛型可以同时指定多个
function fn2<T,K>(a:T,b:K):T{
console.log(b);
return a;
}
fn2<number,string>(123,'hello');
interface Inter{
length:number;
}
//T extends Inter表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a:T):number{
return a.length;
}
class Myclass<T>{
name:T;
constructor(name:T){
this.name=name;
}
}
const mc=new Myclass<string>("孙悟空");
总结
对tyscript的重要知识进行了学习。