一个类实现两个接口,如何用spring实例化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个类实现两个接口,如何用spring实例化相关的知识,希望对你有一定的参考价值。

一个类实现两个接口,如何用spring实例化

spring一般情况下建议使用接口来接受具体的实现类,多态性 , 这样做是为了依赖接口降低耦合 如果你的实现类两个接口那么你可以直接实例化类,比如 你的配置文件里面
<bean id="localeResolver" class="org.springframework.XXXXX"/>
XXXXX为具体实现了接口的类
那么调用的时候试用
AplicationContext ctx =new ClasspathXMLXXX(new String["spring.xml"]);
XXXXX obj = (XXXXX) ctx.getBean("localeResolver");

直接转换成具体的实现类而不是 依赖的接口 如果在其他类中依赖 那么 依赖对象直接写 具体的实现类就可以了
参考技术A 一个类实现多少个接口跟spring实例化没有关系,因为你最后写在配置文件里面的是最后具体的实现类而不是哪个接口 参考技术B 要用接口的哪个方法强制转换到该接口就行了了不是,

如何用父类实例化抽象子类

【中文标题】如何用父类实例化抽象子类【英文标题】:How to instantiate abstract child class with parent class 【发布时间】:2021-01-27 20:54:22 【问题描述】:

我正在尝试制作国际象棋游戏,但在创建对象时遇到了困难。我的思考过程是这样的:

创建一个有 64 个棋子的游戏板,棋子有自己的位置和指向棋子的指针,因此我可以“轻松”加载和卸载棋子。

瓷砖类:

class Tile 
private:
    int x;
    int y;
    Piece* piece;
public:
    Tile(int x, int y) 
        this->x = x;
        this->y = y;
        piece = nullptr;
    
    void loadTile(Piece piece) 
        this->piece = new Piece(piece); //this gives an error
    
    void unloadTile() 
        delete this->piece;
    
;

然后各个部分将从父类继承(您可以在下面看到一个简化的版本)。继承的棋子都将具有相同的构造函数,它们仅在计算可能移动的方式上有所不同。在我看来,这是使用 virtual 函数的最佳方案。

棋子类:

class Piece 
protected:
    int x;
    int y;
public:
    Piece(int x, int y) 
        this->x = x;
        this->y = y;
    
    virtual vector<int> returnPossibleMoves() = 0;
;

class Pawn : public Piece 
public:
    using Piece::Piece;
    vector<int> returnPossibleMoves() 
        vector<int> moves;
        moves.push_back(10); //dont think about this too much
        return moves;
    
;

这就是问题所在 - loadTile() 函数无法实例化片段对象,因为它是抽象的。

我可以看到我的代码可能无法正常工作,因为我尝试使用 Pawn 实例化 Piece,但我真的不知道如何让它工作,或者解决方法是什么。希望你能看到我想要做什么。

【问题讨论】:

请始终初始化基本类型:int x=0, Piece* piece=nullptr.... @Adrian Maire 这是一个有效的观点,但我认为它对我没有帮助 为什么不直接this-&gt;piece = new Pawn(piece) 为什么要实例化一个片对象?你不是总是在孩子班上这样做吗?即你明确地创建了一个Pawn,而不是一个通用的Piece。然后您可以将其用作Piece,但这是另一回事。 @AlanBirtles 有多个部分,这只是一个示例。所以我真的不能只做new Pawn(piece) 当会有 Rook、Bishop 等时 【参考方案1】:

Tile 不知道要实例化哪个 Piece 类型,这是根本问题。

这样的事情呢? (声明,我只是实现了一些想法,代码可能需要大量改进才能达到足够的质量)

#include <array>
#include <cassert>
#include <memory>
#include <vector>

using namespace std;

class Piece;
using CPiecePtr = std::shared_ptr<const Piece>;

enum class PieceType

    Pawn
;

class Pos

    int m_x=0;
    int m_y=0;
public:
    Pos()=default;
    Pos(const Pos&)=default;
    Pos& operator=(const Pos&)=default;
    Pos( int x, int y): m_x(x), m_y(y)
    
        assert(x>=0 && x<8 && y>=0 && y<8);
    
    int x() const  return m_x; 
    int y() const  return m_y; 
;

class Move

    Pos m_origin;
    Pos m_destination;
public:
    Move()=default;
    Move(const Move&)=default;
    Move& operator=(const Move&)=default;
    Move( const Pos& orig, const Pos& dest): m_origin(orig), m_destination(dest)
    
    const Pos& getDestination() const  return m_destination; 
    const Pos& getOrigin() const  return m_origin; 
;
using MoveSet = std::vector<Move>;

class Tile 

private:
    CPiecePtr m_piece;
public:
    void loadTile(CPiecePtr piece)
    
        m_piece = piece;
    
    void unloadTile() 
    
        m_piece = nullptr;
    
    
    void setPiece(CPiecePtr piece) // this is more generic than previous two functions
    
        m_piece = piece;
    
    
    CPiecePtr getPiece() const 
    
        return m_piece;
    
;

class Piece 

    PieceType m_type;
public:
    virtual MoveSet returnPossibleMoves(const Pos&) const = 0;
    Piece(): m_type(PieceType::Pawn)
    
    PieceType getType() const  return m_type; 
;

class Pawn : public Piece 

public:
    MoveSet returnPossibleMoves(const Pos& pos) const override
    
        MoveSet moves;
        moves.push_back(Move(pos, Pos(pos.x(), pos.y()+1)));
        //...
        
        //TODO how to manage special moves? King-rook, replace pawn at end line...
        return moves;
    
;

class Chess

private:
    std::array<std::array<Tile,8>,8> m_board;
    std::vector<CPiecePtr> m_pieces;
public:
    Chess()
    
        m_pieces.push_back( std::make_shared<const Pawn>());
        //...
        
        setPieceAt(Pos(0,1), m_pieces[0]);
    
    
    CPiecePtr getPieceAt( const Pos& pos) const
    
        return m_board[pos.x()][pos.y()].getPiece();
    
    
    void setPieceAt( const Pos& pos, CPiecePtr piece)
    
        return m_board[pos.x()][pos.y()].setPiece(piece);
    
    
    // example:
    MoveSet getMoveSetForPos( const Pos& pos)
    
        const auto& piecePtr = getPieceAt(pos);
        if (nullptr != piecePtr)
        
            return piecePtr->returnPossibleMoves(pos);
        
        return ;
    
    
    void movePiece( const Move& move)
    
        const auto& prevPiece = getPieceAt(move.getOrigin());
        const auto& nextPiece = getPieceAt(move.getDestination());
        assert(prevPiece && !nextPiece);
        
        setPieceAt(move.getDestination(), prevPiece);
        setPieceAt(move.getOrigin(), nullptr);
    
;

int main()

    Chess chess;
   
    const auto& moves = chess.getMoveSetForPos(Pos(0,1));
    if (moves.size()>0)
    
       chess.movePiece(moves[0]);
    
    
    assert( chess.getPieceAt(Pos(0,2))->getType() == PieceType::Pawn);
    
    return 0;

编辑:我对答案不是很自豪,所以我编辑了代码以使其编译。然而,一个完整的国际象棋比这更复杂,我将如何管理王车和其他特殊动作留给读者。

【讨论】:

【参考方案2】:

严格回答这个问题:您不能创建抽象类的实例。这就是不允许使用new Piece 的原因。您必须创建一个非抽象派生类型的实例,例如Pawn,并将片段指针分配给它:

void Tile::loadTile() 
    this->piece = new Pawn; //this is allowed

考虑到这一点,您显然需要进行一些设计更改,其中一些已在您的问题的 cmets 中提及。

【讨论】:

以上是关于一个类实现两个接口,如何用spring实例化的主要内容,如果未能解决你的问题,请参考以下文章

如何用 swig 实例化模板类的模板方法?

C#为啥接口可以实例化一个实现该接口的类?

Spring三种实例化Bean的方式

类继承接口使用接口实例化 与 使用类实例化

█■为啥要用实现接口的类实例化接口呢?

█■为啥要用实现接口的类实例化接口呢? ?